iphone – 可可 – 我发现了我认为是NSDecimalNumber的错误

这是一个简单的代码,显示我认为处理双数时的错误

double wtf = 36.76662445068359375000;
id xxx = [NSDecimalNumber numberWithDouble: wtf];
Nsstring *myBug = [xxx stringValue];
NSLog(@"%.20f",wtf);
NSLog(@"%@",myBug);
NSLog(@"-------\n");

终端将显示两个不同的号码

36.76662445068359375000

36.76662445068359168

这是一个错误还是我错过了什么?

如果第二个数字被舍入,那是一个非常奇怪的四舍五入…

= = = = = = = = = =

我正在编辑原始问题以包含一个WTF错误

尝试这个:

修改原始数字并在10位十进制数字上截断…所以……

double wtf = 36.76662445068359375000;
NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
[formatter setMaximumFractionDigits:10];

Nsstring *valueX = [formatter stringFromNumber:[NSDecimalNumber numberWithDouble:wtf]];
[formatter release];
NSLog(@"%@",valueX);

现在的答案是36.7666244507

现在该值是一个包含10位十进制数字的字符串…现在让我们将其转换回double

double myDoubleAgain = [valueX doubleValue];
NSLog(@"%.20f",myDoubleAgain);

答案是36.76662445070000018177 ??????

myDoubleAgain现在有更多的数字!!!!

解决方法

通常情况下,我是那个进来并向人们解释他们输入的数字不能表示为浮点数的人,并且舍入误差在哪里,等等等等.

这个问题比我们通常看到的要有趣得多,它说明了“浮动点是不精确的,阅读’每个计算机科学家应该知道的……’lolz”的人群智慧究竟是什么问题.

36.76662445068359375不只是任何19位十进制数.它恰好是一个19位十进制数,也可以在双精度二进制浮点中精确表示.因此,初始转换隐含在:

double wtf = 36.76662445068359375000;

确切的. wtf恰好包含b100100.11000100010000011,并且没有发生舍入.

NSDecimalNumber的规范表示它将数字表示为38位十进制尾数和范围为[-127,128]的十进制指数,因此wtf中的值也可以完全表示为NSDecimalNumber.因此,我们可以得出结论,numberWithDouble没有提供正确的转换.虽然我找不到声称这个转换例程被正确舍入的文档,但没有充分的理由不这样做.这是一个真正的错误,please report it.

我注意到iPhoneOS上的字符串格式化程序似乎提供了正确的舍入结果,所以你可以通过首先将double格式化为38位精度的字符串然后使用decimalNumberWithString来解决这个问题.不理想,但它可能适合你.

相关文章

我正在用TitaniumDeveloper编写一个应用程序,它允许我使用Ja...
我的问题是当我尝试从UIWebView中调用我的AngularJS应用程序...
我想获取在我的Mac上运行的所有前台应用程序的应用程序图标....
我是一名PHP开发人员,我使用MVC模式和面向对象的代码.我真的...
OSX中的SetTimer在Windows中是否有任何等效功能?我正在使用...
我不确定引擎盖下到底发生了什么,但这是我的设置,示例代码和...