JavaScript的Math.floor函数失误或实现神秘?

8
    ​document.writeln(Math.floor(43.9));

在浏览器中,这会输出43。

​document.writeln(Math.floor(43.9999));​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​

产生 43

 ​document.writeln(Math.floor(43.999999999999));​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​ 

again 43

However,

    document.writeln(Math.floor(43.99999999999999));

产生44。

为什么是这样呢?在小数点后面连续9个9的神奇数字似乎是15*。

此外,Math.floor函数接受数字对象还是数字值作为参数?


3
您知道0.1 + 0.2 !== 0.3这件事,对吧?:) 您的观察可能是这个主题的一个变化。 - Šime Vidas
2
我猜测(不确定)该函数需要一个浮点数,在返回第一个数字44(带有14个9的数字)时超出了浮点数大小,因此您的常量数字被四舍五入,然后传递给函数。再次强调,这只是一个猜测! - Diego
1
顺便说一下,在我的Firebug控制台中,魔数是15。 - Šime Vidas
3
请看这里:http://jsfiddle.net/k7huV/2/,你可以看到43.99(15个9)实际上是被**存储**为44的。因此,这不是数学算法中的四舍五入问题,而是数字存储方式的问题。 - Travis J
1
@treehau5 我认为15个9足以满足你所需的任何需求。 - Ibu
显示剩余7条评论
5个回答

7
IEEE 754双精度二进制浮点格式(JavaScript使用的“Number”类型)提供了15-17位有效十进制数字的精度。
这意味着它提供了15-17位有效十进制数字的精度。如果一个最多具有15个有效十进制数字的十进制字符串被转换为IEEE 754双精度,然后再转换回同样数量的有效十进制数字,那么最终字符串应该与原始字符串匹配;如果一个IEEE 754双精度被转换为至少17个有效十进制数字的十进制字符串,然后再转换回双精度,那么最终数字必须与原始数字匹配[1]。
来源:http://en.wikipedia.org/wiki/Double-precision_floating-point_format#IEEE_754_double-precision_binary_floating-point_format:_binary64

5

双精度浮点数(也称为doubles)可以存储非常广泛的值,但只有有限的精度——15-17个有效数字。如果您执行以下操作,则会看到发生的情况:

var x = 43.99999999999999;
var y = 43.999999999999999;

document.writeln(x); // 43.99999999999999
document.writeln(y); // 44
document.writeln(Math.floor(x)); // 43
document.writeln(Math.floor(y)); // 44

您会在其他语言中看到相同的情况。例如,PHP:

echo floor(43.99999999999999); // 43
echo floor(43.999999999999999); // 44

2
在Chrome浏览器中,如果我只是在控制台中输入43.99999999999999999999999,它会输出44,这可能就是你遇到的问题。浮点数是近似值。

1

请参考以下解决方案:

http://jsfiddle.net/k7huV/3/

var x = 43;
for( var i = 0; i < 16; i++ ){
    if( i == 0 ) x += ".";
    x += "9";   
}
document.writeln(x);
document.writeln(parseInt(x));

输出:43.9999999999999999 43 正确将43.999999999999999向下取整到43。

1

您可以传递Number的实例,也可以传递数字字面量。

Math.floor(43.99999999999999);

Math.floor(new Number(43.99999999999999));

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接