53 * .01 = .531250

发布于 2024-09-19 02:24:28 字数 1600 浏览 2 评论 0原文

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

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

当我在每次 time= 之间扔一个 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 时,它变成 0.53125。我也尝试过 intValue ,它做了同样的事情。

I'm converting a string date/time to a numerical time value. In my case I'm only using it to determine if something is newer/older than something else, so this little decimal problem is not a real problem. It doesn't need to be seconds precise. But still it has me scratching my head and I'd like to know why..

My date comes in a string format of @"2010-09-08T17:33:53+0000". So I wrote this little method to return a time value. Before anyone jumps on how many seconds there are in months with 28 days or 31 days I don't care. In my math it's fine to assume all months have 31 days and years have 31*12 days because I don't need the difference between two points in time, only to know if one point in time is later than another.

-(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;
    }
}

When passed that very string listed above the result should be 414333.53, but instead it is returning 414333.531250.

When I toss an NSLog in between each time= to track where it goes off I get this result:

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

So that last floatValue returned 53.0000 but when I multiply it by .01 it turns into .53125. I also tried intValue and it did the same thing.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

北城孤痞 2024-09-26 02:24:28

欢迎来到浮点舍入错误。如果您想要精度为固定小数点后两位数,请乘以 100(对于 2 位小数点),然后使用 round() 将其除以 100。只要数字不是太大(占用的空间比我认为的 57 位多)那么你应该没问题,并且在除法上不会有任何舍入问题。

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

Welcome to floating point rounding errors. If you want accuracy two a fixed number of decimal points, multiply by 100 (for 2 decimal points) then round() it and divide it by 100. So long as the number isn't obscenely large (occupies more than I think 57 bits) then you should be fine and not have any rounding problems on the division back down.

EDIT: My note about 57 bits should be noted I was assuming double, floats have far less precision. Do as another reader suggests and switch to double if possible.

朦胧时间 2024-09-26 02:24:28

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

IEEE floats only have 24 effective bits of mantissa (roughly between 7 and 8 decimal digits). 0.00125 is the 24th bit rounding error between 414333.53 and the nearest float representation, since the exact number 414333.53 requires 8 decimal digits. 53 * 0.01 by itself will come out a lot more accurately before you add it to the bigger number and lose precision in the resulting sum. (This shows why addition/subtraction between numbers of very different sizes in not a good thing from a numerical point of view when calculating with floating point arithmetic.)

彩扇题诗 2024-09-26 02:24:28

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

This is from a classic floating point error resulting from how the number is represented in bits. First, use double instead of float, as it is quite fast to use on modern machines. When the result really really matters, use the decimal type, which is 20x slower but 100% accurate.

欢你一世 2024-09-26 02:24:28

您可以使用 +dateWithString: 方法从这些 NSString 日期创建 NSDate 实例。它采用格式为 YYYY-MM-DD HH:MM:SS ±HHMM 的字符串,这就是您正在处理的内容。一旦有了两个 NSDate,您就可以使用 -compare: 方法来查看哪一个时间较晚。

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.

深海蓝天 2024-09-26 02:24:28

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

You could try multiplying all your constants by by 100 so you don't have to divide. The division is what's causing the problem because dividing by 100 produces a repeating pattern in binary.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文