? .9 - .8999999999999995
它会给我这个答案:
0.00000000000000055511151231257827
文档说double有15-16位精度,但它给了我一个具有32位精度的结果。那么所有额外的精度是从哪里来的呢?
答案只有15-16个数字,前导零不计入。这个数字实际上更像是5.5511151231257827×10-16。尾数部分有15-16位数字。指数(-16)将小数点向左移动16位,但并不改变整个数字的位数。
得到一些评论后,我现在对真正发生的事情很好奇。我将所讨论的数字插入到了这个IEEE-754转换器中。它将最后的“27”四舍五入为“30”,但我认为这并没有改变结果。
转换器将数字分解为三个二进制部分:
符号:0(正数)
指数:-51
尾数:1.0100000000000000000000000000000000000000000000000000(二进制表示1.2510)
因此,这个数字是1.012 × 2-51,或者1.2510 × 2-51。由于只存储了三个有效的二进制数字,这表明Lars可能说对了什么。它们不能是“随机噪声”,因为它们每次转换数字时都是相同的。
数据表明,唯一存储的数字是“5”。前导零来自指数,其余看似随机的数字来自计算2-51。
Convert.ToSingle("9111111.4999999990")
和convert.ToSingle("9111111.4999999991")
将出现更有趣的行为。这两个值都比9111112更接近于9111111,但后者会四舍五入。 - supercat你应该阅读:计算机科学家应该了解的浮点数算术知识。
基本上归结为浮点数以有限精度存储。您必须使用一些 delta 进行比较。
if(.9 - .8999999999999995 <= 0.0001)
//close enough to be equal
在浮点数中,前导零并不影响精度(就浮点数而言--数学上,它们是有意义的)。前导零是由浮点数内部表示的指数部分引起的。
数字段55511151231257827
(也称为尾数或有效数字)有17位十进制数字,这足以接近15-16位数字。
@Lars D: 你认为正确的东西,只有在问题的背景下才是正确的。 .9 - .8999999999999995
得到的浮点数的有效数字为0.625,指数为-50。将0.625 * 2-50得到5.5511151231257827e-16。现在,在原问题的背景之外,我们有一个具有17个有效数字的数字,这恰好是0.0000000000000005的最佳二进制逼近值。然而,对于浮点数的表示来说,那些前导零仍然不重要。
? .9 - .8999999999999995
这个减法过程,使用15-16位有效数字,得到结果:
0.0000000000000005
其余的数字只是舍入误差。然而,由于计算机总是在第一个非零数字后存储15-16位有效数字,所以会显示舍入误差,并产生很多尾随的随机数字。因此,结果有来自减法操作的16位有效数字加上来自结果存储的16位数字,共32位。
我认为这是因为在二进制系统中,5是周期性的,因为它不能被2整除。然后Mark Rushakoff所说的就适用了。