About Javascript:1.265*10000=126499.99999999?

1.265 * 10000 = 126499.99999999999?

本问题已经有最佳答案,请猛点这里访问。

当我将1.265乘以10000时,使用javascript时得到126499.9999999999。

为什么会这样?


浮点数在任何情况下都不能正确处理小数。退房

  • http://en.wikipedia.org/wiki/floating-point_number准确性问题
  • http://www.mredkj.com/javascript/nfbasic2.html

您应该知道,计算机中的所有信息都是二进制的,不同碱基中分数的展开式也各不相同。

例如,基10中的1/3=0.333333333333333333333333,而基3中的1/3等于0.1,基2中的1/3等于0.0101010101。

如果您不完全了解不同的基础如何工作,下面是一个示例:

以4为基数的数字301.12。以10为底,等于3*4^2+0*4^1+1*4^0+1*4^-1+2*4^-2=3*4^2+1+1*4^-1+2*4^-2=49.375。

现在,浮点精度的问题来自有效位的有限位数。浮点数有3个部分,一个符号位、指数和尾数,最有可能的是JavaScript使用32或64位IEEE754浮点数标准。对于更简单的计算,我们将使用32位,因此浮点中的1.265将是

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

因此,1.625的最终IEEE754单(32位)表示是:

1
2
Sign Bit(+)      Exponent (0)       Mantissa (1.625)
0                 01111111          01000011110101110000101

现在1000人将是:

符号位(+)指数(9)尾数(1000)0 100001000 111101000000000000万

现在我们要把这两个数相乘。浮点乘法包括将隐藏的1重新添加到两个尾数,将两个尾数相乘,从两个指数中减去偏移量,然后将这两个指数相加。在此之后,尾数必须再次标准化。

前1.010000111101011110000101*1.11110100000000000000000=10.01111100001111111111000000000000000(这是一种痛苦)

很明显,我们有一个9的指数,一个0的指数,所以我们保持10001000作为我们的指数,我们的符号位不变,所以剩下的就是标准化。

我们需要我们的尾数是1.000000的形式,所以我们必须将它右移一次,这也意味着我们必须增加我们的指数,使我们达到1000001,现在我们的尾数被规范化为1.00111100000111111111111100000000000000。它必须被截断为23位,所以我们只剩下1.00111100001111111111111(不包括1,因为它将隐藏在我们的最终表示中),所以我们剩下的最终答案是

1
2
Sign Bit (+)   Exponent(10)   Mantissa
0              10001001       00111100001111111111111

最后,如果我们把这个答案转换回十进制,我们得到(+)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的问题,并且使用了单浮点,而不是双浮点,但概念保持不变。您使用lose accuracy是因为浮点表示法在尾数中只有这么多的位来表示任何给定的数字。

希望这有帮助。


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


另一方面,126500等于126499.9999999….:)

就像1等于0.999999999…

因为1=3*1/3=3*0.333333…=0.999999999….


读一读这篇文章。从本质上讲,计算机和浮点数并不完美地结合在一起!


纯粹是由于浮点表示的不准确。

您可以尝试使用math.round:

1
var x = Math.round(1.265 * 10000);


如果需要解决方案,请停止使用float或double,并开始使用bigdecimal。检查bigdecimal实现stz-ida.de/html/oss/js_bigdecimal.html.en


这里有一个方法可以解决你的问题,尽管可以说不是很好:

1
2
3
4
5
6
7
var correct = parseFloat((1.265*10000).toFixed(3));

// Here's a breakdown of the line of code:
var result = (1.265*10000);
var rounded = result.toFixed(3); // Gives a string representation with three decimals
var correct = parseFloat(rounded); // Convert string into a float
                                   // (doesn't show decimals)

这些小错误通常是由语言使用的浮点精度引起的。有关浮点数精度问题的更多信息,请参阅此维基百科页面。


你可能想读这个。


甚至在MS JScript引擎上添加了:Wscript.echo(1083.6-1023.6)给出59.9999999