13

ECMAScript 规范Math.pow具有以下特殊规则:

  • 如果 x < 0 且 x 是有限的且 y 是有限的且 y 不是整数,则结果为 NaN。

( http://es5.github.com/#x15.8.2.13 )

结果是Math.pow(-8, 1 / 3)给出NaN而不是-2

这个规则的原因是什么?这条规则是否有某种更广泛的计算机科学或 IEEEish 原因,或者它只是 TC39/Eich 曾经做出的选择?


更新

感谢Amadan与我的交流,我想我现在明白了其中的道理。为了后代,我想扩展我们的讨论。

让我们看下面的例子:Math.pow(823543, 1 / 7)虽然6.999999999999999它确实应该是7. 这是由于1 / 7必须首先转换为十进制表示而导致的不准确性0.14285714285714285,该表示被截断并失去精度。当我们使用正数时,这并不是一个糟糕的问题,因为我们仍然会得到非常接近真实结果的结果。

然而,一旦我们踏入消极的世界,我们就会遇到问题。如果一个 JavaScript 引擎要尝试计算Math.pow(-823543, 1 / 7),它首先需要转换1 / 7为小数,所以它Math.pow(-823543, 0.14285714285714285)实际上是没有真正答案的计算。在这种情况下,它可能不得不返回,NaN因为它找不到实数,即使真正的答案应该是-7。此外,寻找接近实数的复数以进行“最佳猜测”可能涉及一定程度的复杂性,他们不希望在数学领域中需要 JS 引擎。

我的猜测是由于考虑到浮点数的精度损失,导致他们得出这样的规则:负数的非整数幂应该总是NaN——基本上是因为非整数幂可能会给出由于精度损失而导致的复数,即使它不应该,并且可能没有好的方法可以从中恢复。

对此,我相当满意,但我欢迎进一步的信息。

4

2 回答 2

4

我假设是因为这些情况导致结果进入复杂的领域,并且 ECMAScript 没有配备虚数。具体来说,您的示例应该会产生接近于 的1 + 1.732i结果,以及其他结果。(事实上​​,-2 也是一个可能的结果并不重要 - 这是一个意外而不是规则。)

于 2013-01-29T04:35:45.147 回答
2

您可以使用辅助函数。

我很快就遇到了类似的情况。这是为您提出的解决方案:

function checkSquareRoot(x, y) {
    if (x > 0) {
        return Math.pow(x, y)
    }
    return -1 * Math.pow(-x, y)
}
于 2015-10-04T05:10:32.060 回答