有些问题,我无法理解。
请看这段代码:
<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。 请解释一下这种行为的原因。 提前致谢。
有些问题,我无法理解。
请看这段代码:
<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。 请解释一下这种行为的原因。 提前致谢。
好的,让我来解释一下。
要记住的基本事实是:浮点数占用有限的位数,并试图使用二进制算术表示原始数字。
正如您所知,在二进制算术中,整数由它们包含的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的倒数的倍数。因此,0.75(十进制中的)(即3/4)将被表示为1/2 + 1/4,这意味着0.11(在二进制中)。正如十进制不足以有限方式表示每个小数一样,给定有限空间的情况下,二进制也不能表示所有小数。
现在,尝试用二进制表示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,得到13/800。下一个是1/64,你剩下1/1600,因此下一个是1/2048等等。因此我们得到了0.00011100001,但它继续下去;你会发现总是有一部分是分数。现在,我没有计算整个过程,但是在小数点后放入32个二进制数字后,你仍然可能有一些分数剩余(这假设所有32位空间都用于表示小数部分,但实际上并非如此)。因此,我相信你能理解结果可能与其实际值有所不同。// 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
它的工作原理是首先将浮点数乘以10^3
(1000)用于三位小数,或者10^2
(100)用于两位小数。 然后对其进行四舍五入并将其除回原始大小。
Math.pow(10, d)
使10^d
(这意味着d
将给我们1000)。
在您的情况下,请执行alert(dec(y,2));
,它应该可以工作。
使用浮点数,您可以获得您尝试编码的数字的表示。大多数情况下,它是一个非常接近原始数字的数字。有关编码/存储浮点数的更多信息,请单击此处。
注意: 如果您显示x的值,它仍然显示0.011,因为JavaScript尚未确定变量类型x。但是,在将其乘以10之后,类型被设置为浮点数(这是唯一的可能性),并且显示了舍入误差。