Javascript 1.265 * 10000 = 126499.99999999999?

Javascript 1.265 * 10000 = 126499.99999999999?,javascript,floating-point,floating-accuracy,Javascript,Floating Point,Floating Accuracy,当我将1.265乘以10000时,使用Javascript时得到126499.9999999999 为什么会这样?浮点数不能在所有情况下正确处理小数。退房 这是浮点表示错误的结果。并非所有具有有限十进制表示的数字都具有有限二进制浮点表示 读一读。从本质上讲,计算机和浮点数并不完美地结合在一起 纯粹是因为表述不准确 您可以尝试使用: 这些小错误通常是由语言使用的浮点精度引起的。有关浮点精度问题的更多信息,请参阅。另一方面,126500等于126499.9999999…..) 就像 因为1=3

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


为什么会这样?

浮点数不能在所有情况下正确处理小数。退房


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

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

纯粹是因为表述不准确

您可以尝试使用:


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

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

就像


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

MS JScript引擎上的偶数添加:
WScript.Echo(1083.6-1023.6)给出了59.9999999

以下是一种克服您的问题的方法,尽管可以说不是很漂亮:

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)

你应该知道,计算机中的所有信息都是二进制的,并且分数在不同基数下的展开式也不同

例如,基数10中的1/3=.33333,而基数3中的1/3等于.1,基数2中的1/3等于.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

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

0的符号位(0表示正,1表示负)0的指数(即指数+偏移量,因此无符号二进制中为127)011111111(最后我们得到了1.265的符号,ieee浮点标准使用了隐藏的1表示,因此1.265的二进制表示为1.010000111010111000010101,忽略了1:)0100001110101110000101

因此,1.625的最终IEEE 754单(32位)表示为:

Sign Bit(+)      Exponent (0)       Mantissa (1.625)
0                 01111111          01000011110101110000101
现在,1000将是:

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

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

第一个1.010000111010111100000101*1.11110100000000000000000=10.0111110000111111111111000000000000000 (这是一种痛苦)

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

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

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

虽然我简化了将1000乘以1.265(而不是10000)的问题,并使用单浮点数而不是双浮点数,但概念保持不变。因为浮点数表示法在尾数中只有如此多的位来表示任何给定的数字,所以使用“丢失精度”


希望这能有所帮助。

如果您需要解决方案,请停止使用浮点或双精度,开始使用BigDecimal。
检查BigDecimal实现

我们可以将此链接到其他浮点错误问题吗?您可能希望首先使用全整数进行计算以避免此行为。“我们可以将此链接到…”当然,如果有人记得第一次问这个问题是什么时候。每次都能得到如此多的答案,如此之快,以至于我从未想过要把我的两分钱放进去,所以我没有……如果你所关心的是它打印12650,不管内部表示如何,你可以尝试这样的方法:var myVariable=1.265*10000;document.write(myVariable.toFixed(0));还有…为什么(e^pi)-pi=19.9990979918947?为什么匿名投票?这不是问题的直接答案,但这是一个数学真理,它部分解释了为什么计算机以这种方式计算。在这个问题中,没有…这不是一个关于循环小数表示非唯一性的问题,而是关于浮点小数的准确性的问题陈述。哦,真的吗?在做出这样的陈述之前,我至少会对这个主题做一些研究。这个证明在数学上是100%正确的。你的数学陈述是正确的,activa,但它没有回答最初的问题。我完全同意这个答案。这是一个答案,因为他问“为什么”。这很好地解释了为什么。我本来打算发布一个类似的答案,但发现你已经回答正确了。谢谢!你真的能用javascript做到吗?是的,你能。看看这里,它实际上是Java的BigDecimal和MathContext类的一个重新实现。BigDecimal库非常适合这种东西。对于很多精度的数字来说,它真的很慢但是对于像钱这样的东西来说,它是一个g
Sign Bit (+)   Exponent(10)   Mantissa
0              10001001       00111100001111111111111