2

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

我的日期采用字符串格式 @"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;
    }
}

当传递上面列出的那个字符串时,结果应该是 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

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

4

5 回答 5

10

欢迎来到浮点舍入错误。如果你想要精度两个固定的小数点,乘以 100(2 个小数点)然后再round()除以 100。只要这个数字不是太大(占用超过我认为的 57 位)那么你应该没问题,并且在除法上没有任何舍入问题。

编辑:应该注意我关于 57 位的注释我假设是双精度的,浮点数的精度要低得多。按照另一位读者的建议做,如果可能的话切换到双倍。

于 2010-09-08T21:11:32.977 回答
6

IEEE 浮点数只有 24 位有效尾数位(大约在 7 到 8 位十进制数字之间)。0.00125 是 414333.53 和最接近的浮点表示之间的第 24 位舍入误差,因为确切的数字 414333.53 需要 8 个十进制数字。53 * 0.01 在您将其添加到更大的数字并失去结果总和的精度之前,它本身会更加准确。(这说明了为什么在使用浮点运算进行计算时,从数值的角度来看,大小非常不同的数字之间的加法/减法并不是一件好事。)

于 2010-09-08T23:45:36.220 回答
2

这是由于数字以位表示的方式导致的经典浮点错误。首先,使用 double 而不是 float,因为它在现代机器上使用起来相当快。当结果真的很重要时,请使用小数类型,它慢 20 倍但 100% 准确。

于 2010-09-08T21:19:47.240 回答
2

You can create NSDate instances form those NSString dates using the +dateWithString: method. It takes strings formatted as YYYY-MM-DD HH:MM:SS ±HHMM, which is what you're dealing with. Once you have two NSDates, you can use the -compare: method to see which one is later in time.

于 2010-09-09T03:33:08.810 回答
1

您可以尝试将所有常量乘以 100,这样您就不必除以。除法是导致问题的原因,因为除以 100 会产生二进制的重复模式。

于 2010-09-09T03:24:06.757 回答