Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/iphone/40.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/flutter/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Iphone 可可-I';我发现了一个我认为是小数的错误_Iphone_Cocoa_Iphone Sdk 3.0 - Fatal编程技术网

Iphone 可可-I';我发现了一个我认为是小数的错误

Iphone 可可-I';我发现了一个我认为是小数的错误,iphone,cocoa,iphone-sdk-3.0,Iphone,Cocoa,Iphone Sdk 3.0,下面是一个简单的代码,它显示了我认为在处理双倍数字时存在的错误 double wtf = 36.76662445068359375000; id xxx = [NSDecimalNumber numberWithDouble: wtf]; NSString *myBug = [xxx stringValue]; NSLog(@"%.20f", wtf); NSLog(@"%@", myBug); NSLog(@"-------\n"); 终端将显示两个不同的数字 36.766624450683

下面是一个简单的代码,它显示了我认为在处理双倍数字时存在的错误

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.7666244507000018177


MyDouble现在又有了更多的数字

尝试使用
双精度
超出大约16位十进制精度通常是错误的。坦率地说,我很惊讶您能够以一种在注销时保持这种精度的方式来表示这个
双精度
(有19个有效数字)。你甚至可能会在iPhone上看到不同的行为,它将长双精度
类型映射为普通的双精度
(你的Mac可能会在幕后处理长双精度)

您看到的舍入可能发生在二进制级别(),因此您不会看到预期的十进制舍入

正是由于这些原因,如果您需要这种高精度数学,您将希望从头到尾完全使用nsdecimalnumber或NSDecimals。为此,不要在浮点类型之间进行转换,而是直接使用NSStrings填充和导出数字(或将其作为NSDEcimalNumber存储在核心数据中)

例如,您可以使用以下代码解决上述问题:

id xxx = [NSDecimalNumber decimalNumberWithString:@"36.76662445068359375000"];

NSDecimalNumbers(及其C结构等价物NSDecimal)最多可以处理38位有效数字。

通常,我会进来向人们解释,他们输入的数字不能表示为浮点数,在舍入错误的地方,诸如此类

这个问题比我们通常看到的要有趣得多,它准确地说明了“浮点是不精确的,读一下‘每个计算机科学家都应该知道的……’”这句话的群众智慧的错误所在

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

double wtf = 36.76662445068359375000;
这是准确的
wtf
精确地包含
b100100.1100010001000011
,并且没有发生舍入

NSDecimalNumber的规范规定,它将数字表示为38位十进制尾数和[-127128]范围内的十进制指数,因此
wtf
中的值也可以精确表示为NSDecimalNumber。因此,我们可以得出结论,
numberwhithdouble
不能提供正确的转换。虽然我找不到声称此转换例程已正确舍入的文档,但没有理由不舍入这是一个真正的错误


我注意到iPhoneOS上的字符串格式化程序似乎提供了正确的四舍五入结果,因此您可以先将double格式化为精度为38位的字符串,然后使用
decimalNumberWithString
。不理想,但它可能适合您。

不是一个bug,请阅读我想知道还有多少平台仍然会被问到这一点。net:JS和perl:python:C:Java:Real bug而不是dup。请看我的答案。这根本不是一个bug,而是在没有考虑其含义的情况下滥用了API。请参阅,尤其是评论。Marcus是社区中一位受人尊敬的成员。@Mike:您添加的新材料与原始版本无关(将double导入到NSDecimalNumber的问题)。这是试图将小数表示为浮点数的副作用。请参阅毛里西奥和内森链接到的参考资料。如果他没有使用numberWithDouble,你可能会有道理。该消息不是为NSDecimalNumber定义的,而是为其超类NSNumber定义的。NSDecimalNumber没有API提供直接从double创建实例的便利。在这方面做得很好。如果我能为此创建一个可复制的测试用例,我会提交一个bug报告。谢谢,我已经填充了一个bug,我还有另一个证明。我将包括在我的原始问题中。@David Schaefgen:我们希望NSDecimalNumber能够提供自己的numberWithDouble实现,它会覆盖NSNumber实现。@David Schaefgen:即使它只是返回一个NSNumber,而不是NSDecimalNumber,NSNumber应该能够正确地表示这个特定的双精度并将其注销。这里的进口出现了问题。