我正在尝试添加两次,例如 20:30 + 1:40 = 22h 10m。 我对点后的余数有疑问
#include <stdio.h>
float walking (float start,float duration);
int main() {
printf ("finish = %.2f", walking(20.30, 1.40));
return 0;
}
float walking(float start, float duration) {
int finMinuites = (int)(start * 100) % 100 + (int)(duration * 100) % 100;
int finHours = (start * 100) / 100 + (duration * 100) / 100;
if (finMinuites >= 60) {
finMinuites -= 60;
finHours++;
}
if (finHours >= 24)
finHours -= 24;
return finHours + finMinuites / 100;
}
如果您确实想将时间存储在浮点数中,那么这里有一个解决方案:
#include<stdio.h>
#include<math.h>
float walking(float start,float duration);
int main() {
printf("finish = %.2f",walking(20.30, 1.40));
return 0;
}
int toMinutes(float time){
int t = (int)round((time*100));
int hours = t/100;
int min = t - hours * 100;
return hours*60+min;
}
float toFloat(int minutes){
int hours = minutes/60;
int min = minutes - hours * 60;
float t = hours * 100;
t += min;
t /= 100;
return t;
}
float walking(float start,float duration){
int mins = toMinutes(start) + toMinutes(duration);
int day = 24*60;
while(mins > day){
mins -= day;
}
return toFloat(mins);
}
但我建议将分钟存储为 int。
困难的部分是正确地破坏浮点变量(FP)。
float/double
无法表示许多值,例如 0.01 完全 等等
当 (int)(start * 100)
截断时,分钟 * 100 是略小于整数的分数时,(int)
会失败。
而是将 FP 值分解为整数部分和分数部分 (
modf()
) 以获得小时和分钟,然后形成总的单个单位时间值。添加。然后将总和转换回小时.分钟。
使用
double
比使用 float
更有意义,因为 OP 正在使用 double
测试用例常量。此外 float
应保留用于需要/从中受益的强制性条件,而不是默认的 double
。
无需扩展到分钟。使代码更简单。 简单易行.
#include <math.h>
double to_hours(double hours_dot_minutes) {
double h;
double m = modf(hours_dot_minutes, &h) * 100.0;
return h + m/60.0;
}
double reduce_to_a_day(double hours) {
const double hours_per_day = 24.0;
hours = fmod(hours, hours_per_day);
if (hours < 0.0) {
hours += hours_per_day;
}
return hours;
}
double to_hours_dot_minutes(double hours) {
double h;
double m = modf(hours, &h) * 60.0;
return h + m/100.0;
}
double walking(double start, double duration) {
double sum = to_hours(start) + to_hours(duration);
sum = reduce_to_a_day(sum);
return to_hours_dot_minutes(sum);
}
请注意,
int
数学没有在任何地方使用。 IMO,浮点问题最好用 FP 数学处理,整数问题用整数数学处理,文本问题用文本操作处理。混合方法经常会在边缘情况下遇到问题 - 例如 OP 使用 (int)
来解决 FP 问题。
如果仍想在有限的值范围内使用强制转换,
double walking(double start, double duration) {
int start_h = (int) start;
int duration_h = (int) duration;
double sum = start_h + duration_h +
((start - start_h) + (duration - duration_h)) * 100.0 / 60.0;
while (sum >= 24.0) sum -= 24.0;
int sum_h = (int) sum;
return sum_h + (sum - sum_h) * 60.0 / 100.0;
}
按照@ryyker的建议,您可以使用字符串让生活变得简单,而无需更改调用参数:
#include <stdio.h>
#include <stdlib.h>
double walking( double bgn, double dur ) {
printf( "Start = %5.2f duration = %5.2f ", bgn, dur );
char str[32];
sprintf( str, "%.2f %.2f", bgn, dur );
int res = 0, cnt = 1;
for( char *cp = str; ( cp = strtok( cp, " ." ) ) != NULL; cp = NULL )
res += atoi( cp ) * (cnt&1 ? 60 : 1), cnt++;
return res/60%24 + ((res%60)*0.01);
}
int main( void ) {
double pairs[][2] = {
{ 20.30, 1.40 },
{ 1.47, 1.13 },
{ 0.00, 1.13 },
{ 0.00, 0.00 },
{ 23.59, 0.01 },
{ 12.00, 48.27 },
};
for( int i = 0; i < sizeof pairs/sizeof pairs[0]; i++ )
printf ( "finish = %5.2f\n", walking( pairs[i][0], pairs[i][1] ) );
return 0;
}
输出
Start = 20.30 duration = 1.40 finish = 22.10
Start = 1.47 duration = 1.13 finish = 3.00
Start = 0.00 duration = 1.13 finish = 1.13
Start = 0.00 duration = 0.00 finish = 0.00
Start = 23.59 duration = 0.01 finish = 0.00
Start = 12.00 duration = 48.27 finish = 12.27
有人指出,这种方法可能不适用于
Dr Who
和其他能够穿越到过去的时间旅行者。对于那些不适用热力学第二定律的人,以下显示了必要的更改:
sprintf( str, "%.2f %.2f", bgn, dur );
int res = 0, cnt = 1, sgn = 1;
for( char *cp = str; ( cp = strtok( cp, " ." ) ) != NULL; cp = NULL, cnt++ )
res += atoi( cp )
* (cnt&1 ? 60 : 1)
* sgn,
sgn = *cp == '-' ? -1 : 1;
/* then one additional test case */
{ 12.00, -2.30 },
/* Output of the single test case: */
Start = 12.00 duration = -2.30 finish = 9.30
由于OP中显示的第一个参数似乎使用24小时时钟,因此没有尝试从“零下十一点三十分”开始进行测试。
享受你的散步。离开时请把垃圾带走...