具有负数和非整数幂的Math.pow

时间:2013-01-29 04:32:53

标签: javascript floating-point ieee-754 ecmascript-5 ecma262

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

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

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

因此Math.pow(-8, 1 / 3)提供NaN而不是-2

这条规则的原因是什么?是否存在某种更广泛的计算机科学或IEEE推理这一规则的原因,或者它只是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),实际没有真正的答案< / em>的。在这种情况下,它可能必须返回NaN,因为它找不到实数,即使真正的答案应该是-7。此外,寻找接近实数的复数来做出“最佳猜测”可能涉及一定程度的复杂性,他们不希望JS引擎在数学领域拥有。

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

有了这个,我相当满意,但我确实欢迎进一步的信息。

2 个答案:

答案 0 :(得分:4)

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

答案 1 :(得分:0)

您可以使用辅助功能。

在迅速中我遇到了类似的情况。以下是为您提出的解决方案

func checkSquareRoot(x: Double, y: Double) -> Double {
    let result = pow(x, y)

    if x > 0 {
        return result
    } else {
        return -1 * pow( -x, y)
    }
}