2

我在上一个问题中发现Math.pow(0, 0) === 1返回true.

文档中,我们发现以下规则x^y

  • 如果 y 为 NaN,则结果为 NaN。
  • 如果 y 为 +0,则结果为 1,即使 x 为 NaN。
  • 如果 y 为 -0,则结果为 1,即使 x 为 NaN。
  • 如果 x 为 NaN 且 y 为非零,则结果为 NaN。
  • 如果 abs(x)>1 且 y 为 +∞,则结果为 +∞。
  • 如果 abs(x)>1 且 y 为 -∞,则结果为 +0。
  • 如果 abs(x)==1 且 y 为 +∞,则结果为 NaN。
  • 如果 abs(x)==1 且 y 为 -∞,则结果为 NaN。
  • 如果 abs(x)<1 且 y 为 +∞,则结果为 +0。
  • 如果 abs(x)<1 且 y 为 -∞,则结果为 +∞。
  • 如果 x 为 +∞ 且 y>0,则结果为 +∞。
  • 如果 x 为 +∞ 且 y<0,则结果为 +0。
  • 如果 x 为 -∞ 且 y>0 且 y 为奇数,则结果为 -∞。
  • 如果 x 为 -∞ 且 y>0 且 y 不是奇数,则结果为 +∞。
  • 如果 x 为 -∞ 且 y<0 且 y 为奇数,则结果为 -0。
  • 如果 x 为 -∞ 且 y<0 且 y 不是奇数,则结果为 +0。
  • 如果 x 为 +0 且 y>0,则结果为 +0。
  • 如果 x 为 +0 且 y<0,则结果为 +∞。
  • 如果 x 为 -0 且 y>0 且 y 为奇数,则结果为 -0。
  • 如果 x 为 -0 且 y>0 且 y 不是奇数,则结果为 +0。
  • 如果 x 为 -0 且 y<0 且 y 为奇数,则结果为 -∞。
  • 如果 x 为 -0 且 y<0 且 y 不是奇数,则结果为 +∞。
  • 如果 x<0 且 x 是有限的且 y 是有限的且 y 不是整数,则结果为 NaN。

有趣的是,对于任何值x的返回值都是1. 我们能找到返回值 NOT 的任何值x吗?Math.pow(x, 0)1

我在 NodeJS shell 中尝试了以下操作,但我想在浏览器控制台中结果相同:

> Math.pow(undefined, 0)
1
> Math.pow(Date(), 0)
1
> Math.pow("asd", 0)
1
> Math.pow(function () {}, 0)
1
> Math.pow(function () { return 3}, 0)
1
> Math.pow([], 0)
1
> Math.pow(null, 0)
1

也许我们找到了一个 JS 技巧来做到这一点,就像在x === x // false(where isNaN(x) === false)的情况下一样。


只是为了澄清:y将永远是0。只是x在变。

4

4 回答 4

8

您从文档中复制/粘贴的内容包括以下要求:

  • 如果 y 为 +0,则结果为 1,即使 x 为 NaN

因此,您的问题的答案似乎是“否”

于 2013-11-14T11:58:06.653 回答
6

不,永远不会出现任何结果不会运行的情况。该函数的定义指出:

  • 如果 y 为 NaN,则结果为 NaN。
  • 如果 y 为 +0,则结果为 1,即使 x 为 NaN。
  • 如果 y 为 -0,则结果为 1,即使 x 为 NaN。

所有参数在运行之前都被强制转换为数字类型,因此无论它是 1。如果多个结果适用,则第一个适用的结果是返回的结果,在这种情况下为1.

正如您所说,y 是 0,因此它不是NaN,因此不会返回 NaN。

ES5 §15.8.2

以下每个 Math 对象函数都将 ToNumber 抽象运算符应用于其每个参数(如果有多个参数,则按从左到右的顺序),然​​后对生成的 Number 值执行计算。

任何不是数字(或满足数字格式的字符串)的参数都将被强制为 0(对于null和) false""1(对于true)或 NaN(其他任何值)。

于 2013-11-14T11:58:07.333 回答
2

对,因为您使用的是运行 V8 的 node.js,所以让我们看看源代码

函数Math.pow定义在math.js并声明:

function MathPow(x, y) {
  return %_MathPow(TO_NUMBER_INLINE(x), TO_NUMBER_INLINE(y));
}

TO_NUMBER_INLINE用于将任何类型转换为数值。因此,在_MathPow操作中,我们将数字作为参数。

让我们继续前进hydrogen.cc,它具有引用指令的MathPow调用的实现。后者使用中定义的方法计算功率。这里我们终于有了计算的逻辑:HPowerhydrogen-instructions.ccpower_helper(c_left->DoubleValue(), c_right->DoubleValue())assembler.cc

double power_helper(double x, double y) {
  int y_int = static_cast<int>(y);
  if (y == y_int) {
    return power_double_int(x, y_int);  // Returns 1 if exponent is 0.
  }

  // ...
}

注释(从源代码复制)说明了一切,甚至不需要检查同一个文件中定义的内容来说明作为第一个参数power_double_int传递给的每个值都将返回。Math.powy == 01

要说绝对让我们检查一下power_double_int

double power_double_int(double x, int y) {
  double m = (y < 0) ? 1 / x : x;
  unsigned n = (y < 0) ? -y : y;
  double p = 1;
  while (n != 0) {
    if ((n & 1) != 0) p *= m;
    m *= m;
    if ((n & 2) != 0) p *= m;
    m *= m;
    n >>= 2;
  }
  return p;
}

从上面看,n将永远是0,所以while循环永远不会运行,返回p = 1不变。

于 2013-11-14T12:35:54.490 回答
1

根据 ES5 规范,算法的前三个步骤如下:

  • 如果y为 NaN,则结果为 NaN。
  • 如果y为 +0,则结果为 1,即使x为 NaN。
  • 如果y为 -0,则结果为 1,即使x为 NaN。

如果您正在编写 ES5 标准的实现,您的代码可能看起来像这样:

function pow(x, y) {
    if (isNaN(y)) return NaN;
    if (y === 0) return 1;
    // ... follow the other rules
}

除了when之外,不会有任何值x会导致它返回任何内容。1y === 0

于 2013-11-14T12:08:17.847 回答