【问题标题】:NSDecimalNumber to unsignedLongLong - wrong valueNSDecimalNumber 到 unsignedLongLong - 错误值
【发布时间】:2010-07-22 11:43:56
【问题描述】:

代码如下:

NSNumber* number = [NSDecimalNumber decimalNumberWithString :@"11111111111111111"];
NSLog(@"%@ = %lld", number, [number unsignedLongLongValue]);

我得到输出:

11111111111111111 = 11111111111111112

是已知的错误还是我做错了什么?

更新: 错误报告:https://bugreport.apple.com/cgi-bin/WebObjects/RadarWeb.woa/3/wo/Stnn5Aaocknzx52c64zbN0/5.83.28.0.9

【问题讨论】:

    标签: iphone core-foundation


    【解决方案1】:

    我认为问题在于您在 NSDecimalNumber 上使用了 NSNumber 的 -longLongValue 方法。 NSDecimalNumber 在内部将数字的高精度表示形式存储为小数,但 NSNumber 只是将其保留为 IEEE 754 双精度浮点值。如果我没记错的话,如果您在 NSDecimalNumber 上使用标准的 NSNumber 超类方法,则内部数字首先会转换为双精度数,这会引入像这样的二进制浮点工件。

    正如neoneye 所建议的,解决此问题的一种方法可能是使用NSString 作为中介。例如:

    NSDecimalNumber* number = [NSDecimalNumber decimalNumberWithString :@"11111111111111111"];
    double number2 = [@"11111111111111111" doubleValue];
    
    NSLog(@"%@ = %lld = %f", number, [[number descriptionWithLocale:nil] longLongValue], number2);
    

    将产生结果11111111111111111 = 11111111111111111 = 11111111111111112.000000,显示十进制数提取的正确结果以及此数字临时存储在双精度中时发生的错误。

    【讨论】:

    • “如果我没记错的话,如果你在一个 NSDecimalNumber 上使用标准的 NSNumber 超类方法,内部数字首先被转换为一个双精度数,这会引入像这样的浮点伪像”你从哪里得到的此信息?这听起来很奇怪,我几乎不相信。在大多数情况下,我们通过 NSNumber 接口使用实例,我们不应该考虑使用哪个具体的子类来构造这个实例。
    • @iKiR - 这里有一些讨论:stackoverflow.com/questions/2479100/…,这里指向 Marcus 的 cmets:cimgf.com/2008/04/23/…,但这并没有完全说明这种情况。当我遇到类似问题时,我可能在 cocoa-dev 邮件列表档案中的某个地方找到了这个。是的,这很奇怪,我想我当时提交了一份错误报告。我建议您自己提交另一个。
    • 谢谢布拉德,我在几分钟前提交了一个错误:bugreport.apple.com/cgi-bin/WebObjects/RadarWeb.woa/3/wo/…
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-29
    • 2015-06-23
    相关资源
    最近更新 更多