理解浮点变量

时间:2010-03-19 21:30:21

标签: javascript floating-point

有一些问题,无论如何我无法理解。

请看这段代码


<script type="text/javascript">
function math(x)
{
 var y;
 y = x*10;
 alert(y);
}

</script>
<input type="button" onclick="math(0.011)">

点击按钮后必须提醒什么? 我认为 0.11 ,但不,它发出警报 的 0.10999999999999999 请解释一下这种行为。 提前谢谢

4 个答案:

答案 0 :(得分:9)

确定。让我试着解释一下。

使用浮点数记住的基本要点是:它们占用有限的位并尝试使用base-2算法表示原始数字。

如您所知,在base-2中,算术整数由它们包含的2的幂表示。因此,6将表示为4 + 2,即。二进制为110.

为了理解如何表示小数,您必须考虑我们如何在十进制系统中表示小数。数字的小数部分(例如0.11)表示为10的反幂的倍数(因为基数是10)。因此0.11实际上是1/10 + 1/100。您可以理解,这并不足以代表有限位数的所有小数。例如,1/3将是0.333333 ....以永无止境的方式。如果我们只有32位数的空格来写下数字,我们最终只会得到原始数字的近似值,即0.33333333333333333333333333333333。例如,如果它乘以3而不是1,则该数字将给出0.99999999999999999999999999999999。

基数为2的情况类似。每个分数都表示为2的反幂的倍数。因此0.75(十进制)(即3/4)将表示为1/2 + 1/4,这意味着0.11(在基数-2中)。正如基数10不足以以有限的方式表示每个分数,基数2不能代表给定有限空间量的所有分数。

现在,尝试在base-2中表示 0.11 ;你从 11/100 开始,并试图找到一个小于这个数的2的逆幂。 1/2 不起作用, 1/4 也不起作用, 1/8 也不起作用。 1/16 符合条件,因此您在小数点后的第4位标记1并从 11/100 中减去 1/16 。你剩下 19/400 。现在尝试找到符合描述的下一个2的幂。 1/32 似乎是那个,在该点之后标记第5位并从 19/400 中减去 1/32 ,你得到<强>800分之13即可。下一个是 1/64 ,你剩下 1/1600 ,因此下一个一直在 1/2048 等等因此我们得到了 0.00011100001 但它一直在继续;你会发现总有一小部分存在。现在,我没有完成整个计算,但是在点后面放入32位二进制数字后,你仍然可能会留下一些分数(假设所有32位空间都用于表示小数部分,它不是)。因此,我相信您可以理解,结果数字可能与实际值有所不同。

在您的情况下,差异是0.00000000000000001,即1/100000000000000000 = 1/10 ^ 17,我相信您可以看到为什么会这样。

答案 1 :(得分:5)

这是因为你正在处理浮点数,这是浮点数学的预期行为。

您需要做的就是格式化该数字。

如果你想知道为什么,这也适用于此java explanation

在javascript中,所有数字都表示为64位浮点数,因此您经常遇到这种情况。

该文章的快速概述是浮点试图表示一系列值更大然后适合64位,因此会有一些不精确的表示,这就是你所看到的。

答案 2 :(得分:1)

使用浮点数表示您尝试编码的数字。大部分是非常的数字接近原始数字。有关编码/存储浮点数的更多信息可以在here找到。

注意: 如果显示x的值,它仍然显示0.011,因为JavaScript尚未确定x具有哪种变量类型。但是在将它乘以10之后,类型被设置为浮点(这是唯一的可能性)并且圆错误显示。

答案 3 :(得分:1)

你可以试着用这个来修正小数的nr:

// fl is a float number with some nr of decimals
// d is how many decimals you want
function dec(fl, d) {
  var p = Math.pow(10, d);
  return Math.round(fl*p)/p;
}

例如:

var n = 0.0012345;
console.log(dec(n,6)); // 0.001235
console.log(dec(n,5)); // 0.00123
console.log(dec(n,4)); // 0.0012
console.log(dec(n,3)); // 0.001

首先将float与10^3(1000)乘以三位小数,或10^2(100)乘以两位小数。然后围绕它并将其分成原始尺寸 Math.pow(10, d)生成10^d(意味着d会给我们1000)。

在您的情况下,执行alert(dec(y,2));,它应该有效。