JavaScript整数除法结果为浮点数,是否可能存在舍入误差?

3
我知道在JavaScript中,例如 1.005*100 / 100 这样的例子会产生略微不准确的结果(100.49999999999999),这是浮点设计固有的问题。
我的问题是是否可以在不使用字符串操作的情况下生成可靠的小数舍入程序。
x 是一个整数时,x / 100(int/int=float)是否会产生视觉上的不准确性? (即 ..000001..99999) 最好提供一个证明的示例。
如果答案是肯定的,那么在 JavaScript 中可靠地将小数点向左移动的唯一方法就是使用字符串操作(即 MDN 的 Math.round10),并承受适度的性能损失。

1
你可以在0到99的整数上检查它,自己看看,因为对于更大的数字,它们只是一个整数+与0/100->99/100相同的小数部分。我个人没有发现任何视觉上的不准确之处。 - hdl
@hdl,你说得对,测试并不难。 :-) - 700 Software
2个回答

3
根据这个测试,整数除以整数时没有任何不准确的地方。

var multipliers = [10, 100, 1000, 10000, 100000, 1000000]
for(var i = 0; i < 100000; i++) {
    multipliers.forEach(function (mul) {
        var x = i / mul
        if(x != x.toFixed(6))
            document.write('found one! ' + i + ' / ' + mul + ' = ' + x + '<br/>')
    })
}
document.write('done!')

很好。这意味着一个健壮的四舍五入函数可以在不进行字符串操作的情况下创建出来。:-)

1
要小心处理边缘情况,即超过64位浮点精度的指数较大的大数。尝试打印1.0e23 / 100,由于舍入误差,得到了999999999999999900000,使用toFixed(6)给出了999999999999999868928.000000 - hdl
谢谢。我猜想差异的原因是因为“1.0e23”无法用“int”或“long”表示,因此必须存储为浮点数。无论如何,我不关心那么远的精度。 :-) - 700 Software
不,JS数字始终是64位fp数字,即具有52(+1)位尾数。这意味着可以使用隐式位和符号位表示[| -2^53 , 2^53 |]中的整数。但是在JS中没有intlong(请参见http://www.w3schools.com/js/js_numbers.asp)。 - hdl

1
为了明确我的评论,小数部分仅在无限精度下保持不变,而JS IEEE-754兼容浮点算术并不支持无限精度。有限精度下,您可能无法准确表示一个整数的浮点数(例如,许多整数> 2 ^ 53)。当将x除以100时,您实际上可能得到一个数值上不等于x/100的数字。例如,设x = 1.0e23,IEEE 754双精度中,x约为99999999999999991611392,然后x/100 = 999999999999999916113.92,但由于此数字在双精度中不能表示,因此四舍五入为999999999999999868928。

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