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