1.265*10000 = 126499.99999999999?

vla*_*ruz 6 javascript floating-point floating-accuracy

当我将1.265乘以10000时,使用Javascript时得到126499.99999999999.

为什么会这样?

JSc*_*her 11

您应该知道计算机中的所有信息都是二进制的,并且不同基础中的分数的扩展会有所不同.

例如,基数10中的1/3 = .33333333333333333333333333,而基数3中的1/3等于.1,而基数2中的1/3等于.0101010101010101.

如果你没有完全理解不同的基础如何工作,这是一个例子:

基数4为301.12.将等于3*4 ^ 2 + 0*4 ^ 1 + 1*4 ^ 0 + 1*4 ^ -1 + 2*4 ^ -2 = 3*4 ^ 2 +1 + 1*4 ^ -1基数10 + 2*4 ^ -2 = 49.375.

现在浮点精度的问题来自有效数中有限的位数.浮点数有三个部分,一个符号位,指数和尾数,很可能javascript使用32或64位IEEE 754浮点标准.对于更简单的计算,我们将使用32位,因此浮点数为1.265

符号位为0(0为正,1为负)指数为0(其中127为偏移,即指数+偏移,因此无符号二进制为127)01111111(最后我们得到1.265的符号,ieee浮点标准使用隐藏的1表示,所以我们的二进制表示1.265是1.01000011110101110000101,忽略1 :) 01000011110101110000101.

所以我们最终的IEEE 754单(32位)表示为1.625:

Sign Bit(+)      Exponent (0)       Mantissa (1.625)
0                 01111111          01000011110101110000101
Run Code Online (Sandbox Code Playgroud)

现在1000将是:

符号位(+)指数(9)尾数(1000)0 10001000 11110100000000000000000

现在我们必须乘以这两个数字.浮点乘法包括将隐藏的1重新添加到两个尾数中,将两个尾数相乘,从两个指数中减去偏移量,然后将两个指数相加.在此之后,必须再次对尾数进行归一化.

首先1.01000011110101110000101*1.11110100000000000000000 = 10.0111100001111111111111111000100000000000000000(这个乘法很痛苦)

现在显然我们有一个9 +指数为0的指数,所以我们保持10001000作为指数,我们的符号位保持不变,所以剩下的就是归一化.

我们需要我们的尾数为1.000000,所以我们必须将它向右移动一次,这也意味着我们必须增加指数,使我们达到10001001,现在我们的尾数被归一化为1.00111100001111111111111111000100000000000000000.它必须被截断为23位,所以我们留下1.00111100001111111111111(不包括1,因为它将隐藏在我们的最终表示中)所以我们留下的最终答案是

Sign Bit (+)   Exponent(10)   Mantissa
0              10001001       00111100001111111111111
Run Code Online (Sandbox Code Playgroud)

最后,如果我们将这个答案转换回十进制,我们得到(+)2 ^ 10*(1 + 2 ^ -3 + 2 ^ -4 + 2 ^ -5 + 2 ^ -6 + 2 ^ -11 + 2 ^ -12 + 2 ^ -13 + 2 ^ -14 + 2 ^ -15 + 2 ^ -16 + 2 ^ -17 + 2 ^ -18 + 2 ^ -19 + 2 ^ -20 + 2 ^ -21 + 2 ^ -22 + 2 ^ -23)= 1264.99987792

虽然我确实简化了问题,将1000乘以1.265而不是10000并使用单个浮点而不是双倍,概念保持不变.您使用丢失准确性,因为浮点表示在尾数中只有很多位,用于表示任何给定的数字.

希望这可以帮助.


Meh*_*ari 5

这是浮点表示错误的结果.并非所有具有有限十进制表示的数字都具有有限的二进制浮点表示.