53*.01 = .531250

bad*_*sel 2 iphone floating-point objective-c nsnumber

我正在将字符串日期/时间转换为数字时间值.在我的情况下,我只是用它来确定某些东西是否比其他东西更新/更旧,所以这个小小数问题不是一个真正的问题.它不需要秒精确.但它仍然让我挠头,我想知道为什么..

我的日期是@"2010-09-08T17:33:53 + 0000"的字符串格式.所以我写了这个小方法来返回一个时间值.在没有人关心的情况下,如果有人在数月内跳了几天,有28天或31天.在我的数学中,可以假设所有月份都有31天,而且年份有31*12天,因为我不需要两个时间点之间的差异,只知道一个时间点是否晚于另一个时间点.

-(float) uniqueTimeFromCreatedTime: (NSString *)created_time {
float time;
    if ([created_time length]>19) {
      time = ([[created_time substringWithRange:NSMakeRange(2, 2)]floatValue]-10) * 535680; // max for 12 months is 535680.. uh oh y2100 bug!
      time=time + [[created_time substringWithRange:NSMakeRange(5, 2)]floatValue] * 44640; // to make it easy and since it doesn't matter we assume 31 days
      time=time + [[created_time substringWithRange:NSMakeRange(8, 2)]floatValue] * 1440;
      time=time + [[created_time substringWithRange:NSMakeRange(11, 2)]floatValue] * 60;
      time=time + [[created_time substringWithRange:NSMakeRange(14, 2)]floatValue];
      time = time + [[created_time substringWithRange:NSMakeRange(17, 2)]floatValue] * .01;
      return time;
    }
    else {
      //NSLog(@"error - time string not long enough");
      return 0.0;
    }
}
Run Code Online (Sandbox Code Playgroud)

当传递上面列出的非常字符串时,结果应该是414333.53,而是返回414333.531250.

当我在每次=之间抛出一个NSLog来跟踪它在哪里时,我得到了这个结果:

time 0.000000
time 401760.000000
time 413280.000000
time 414300.000000
time 414333.000000
floatvalue 53.000000
time 414333.531250
Created Time: 2010-09-08T17:33:53+0000 414333.531250
Run Code Online (Sandbox Code Playgroud)

所以最后一个floatValue返回53.0000但是当我将它乘以.01时它变成.53125.我也试过intValue,它做了同样的事情.

jer*_*jer 10

欢迎使用浮点舍入错误.如果你想准确度两个小数点固定数量,由100(2小数点),然后乘以round()它和这么长时间100除以它的数量不是猥亵大(面积超过我认为57位),然后你应该没事,并且没有任何四舍五入的问题.

编辑:我的注意事项应该注意57位我假设是双倍,浮点数的精度要低得多.做另一位读者建议并尽可能切换到双倍.


hot*_*aw2 6

IEEE浮点数只有24个有效位的尾数(大约在7到8个十进制数字之间).0.00125是414333.53与最近的浮点表示之间的第24位舍入误差,因为确切的数字414333.53需要8位十进制数字.在将其添加到较大的数字并且在所得总和中失去精度之前,53*0.01本身将更准确地出来.(这表示为什么在使用浮点运算进行计算时,从数值的角度来看,非常不同大小的数字之间的加/减是不好的.)