double wtf = 36.76662445068359375000; id xxx = [NSDecimalNumber numberWithDouble: wtf]; Nsstring *myBug = [xxx stringValue]; NSLog(@"%.20f",wtf); NSLog(@"%@",myBug); NSLog(@"-------\n");
终端将显示两个不同的号码
36.76662445068359375000
和
36.76662445068359168
如果第二个数字被舍入,那是一个非常奇怪的四舍五入…
= = = = = = = = = =
尝试这个:
修改原始数字并在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来解决这个问题.不理想,但它可能适合你.
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。