【发布时间】:2014-06-24 23:35:18
【问题描述】:
所以我试图理解 JavaScript 在处理大数字时的行为。考虑以下(在 Firefox 和 Chrome 中测试):
console.log(9007199254740993) // 9007199254740992
console.log(9007199254740994) // 9007199254740994
console.log(9007199254740995) // 9007199254740996
console.log(9007199254740996) // 9007199254740996
console.log(9007199254740997) // 9007199254740996
console.log(9007199254740998) // 9007199254740998
console.log(9007199254740999) // 9007199254741000
现在,我知道为什么它会输出“错误”数字——它试图将它们转换为浮点表示形式,并且正在四舍五入到最接近的可能浮点值——但我不完全确定为什么会这样选择这些特定的数字。我的猜测是它试图四舍五入到最接近的“偶数”,并且由于 9007199254740996 可以被 4 整除,而 9007199254740994 不是,它认为 9007199254740996 更“偶数”。
- 它使用什么算法来确定内部表示?我的猜测是它是常规中点舍入的扩展(舍入到偶数是 IEEE 754 函数中的默认舍入模式)。
- 此行为是作为 ECMAScript 标准的一部分指定的,还是依赖于实现?
【问题讨论】:
-
@RobG:评估
console.log(9007199254740993)涉及两次转换:一次将 JavaScript 代码中的十进制文字转换为内部二进制浮点格式,第二次从内部二进制格式转换为十进制执行log方法时用于控制台输出的字符串。这些转换中的每一个都需要相当复杂的算法(如果做得好的话)。所以说没有算法是不正确的。 -
是的,我认为这不是舍入算法。
-
是的,但舍入是算法的重要组成部分:十进制到二进制的转换必须决定如何将精确的十进制值转换为 IEEE 754 binary64 格式可表示的最接近的数字。正如@PatriciaShanahan 所描述的那样,该决定的一部分涉及选择哪种方式进行舍入,并且通常的约定是使用舍入到偶数。
-
嗯。事实证明,这不仅仅是“常规约定”:ECMA-262 标准明确规定应使用 round-ties-to-even 舍入方法(在第 8.5 节中)。
标签: javascript floating-point floating-point-precision floating-point-conversion