2

I found in a previous question that Math.pow(0, 0) === 1 returns true.

In the documentation we find the following rules for x^y:

  • If y is NaN, the result is NaN.
  • If y is +0, the result is 1, even if x is NaN.
  • If y is −0, the result is 1, even if x is NaN.
  • If x is NaN and y is nonzero, the result is NaN.
  • If abs(x)>1 and y is +∞, the result is +∞.
  • If abs(x)>1 and y is −∞, the result is +0.
  • If abs(x)==1 and y is +∞, the result is NaN.
  • If abs(x)==1 and y is −∞, the result is NaN.
  • If abs(x)<1 and y is +∞, the result is +0.
  • If abs(x)<1 and y is −∞, the result is +∞.
  • If x is +∞ and y>0, the result is +∞.
  • If x is +∞ and y<0, the result is +0.
  • If x is −∞ and y>0 and y is an odd integer, the result is −∞.
  • If x is −∞ and y>0 and y is not an odd integer, the result is +∞.
  • If x is −∞ and y<0 and y is an odd integer, the result is −0.
  • If x is −∞ and y<0 and y is not an odd integer, the result is +0.
  • If x is +0 and y>0, the result is +0.
  • If x is +0 and y<0, the result is +∞.
  • If x is −0 and y>0 and y is an odd integer, the result is −0.
  • If x is −0 and y>0 and y is not an odd integer, the result is +0.
  • If x is −0 and y<0 and y is an odd integer, the result is −∞.
  • If x is −0 and y<0 and y is not an odd integer, the result is +∞.
  • If x<0 and x is finite and y is finite and y is not an integer, the result is NaN.

What is interesting is that for any value of x the returned value is 1. Can we find any value for x for what Math.pow(x, 0) returns a value that is NOT 1?

I tried the following in the NodeJS shell, but I guess it's the same result in the browser console:

> 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

Maybe we find a JS trick that does this, like in the x === x // false (where isNaN(x) === false) case.


Just to clarify: y will be always 0. Only x is changing.

Community
  • 1
  • 1
Ionică Bizău
  • 109,027
  • 88
  • 289
  • 474
  • 4
    Just one question: why do you need it? – VisioN Nov 14 '13 at 11:56
  • 2
    @VisioN To satisfy my curiosity...? Maybe. – Ionică Bizău Nov 14 '13 at 11:57
  • Is there any number, N for which N^0 does not equal 1? Not in the range of natural numbers. For complex numbers, sure. But why would you expect JS to return a value different to that which was computed without the help of a computer?? – enhzflep Nov 14 '13 at 11:59
  • 1
    Mathematically speaking, zero is the only x for which `x pow 0` is not 0, but undefined. Not the JavaScript `undefined`, it's just a mathematical rule saying that there's no logic in `0 pow 0` so it's an undefined result. It could be both anything and nothing. Read this: http://math.stackexchange.com/questions/11150/zero-to-the-zero-power-is-00-1#answer-11155 – Sergiu Paraschiv Nov 14 '13 at 11:59
  • 1
    Doesn't the documentation you pointed out mention pretty clearly that for y = 0 or y=-0, the result is 1, no matter what? – Tibos Nov 14 '13 at 12:00
  • @enhzflep I didn't specified that `x` must be a number. It can be any type of data. – Ionică Bizău Nov 14 '13 at 12:02
  • As has been stated, the documentation answers your question. "If y is ±0" is all you need to know. Any implementation would evaluate y first. If it's 0, it won't evaluate x. – James Allardice Nov 14 '13 at 12:03
  • @SergiuParaschiv `Math.pow(0, 0)` returns `1`, not `undefined`. The question is that having the second argument of the `pow()` function we can obtain a value that is NOT 1. – Ionică Bizău Nov 14 '13 at 12:04
  • @イオニカビザウ - Duly noted and contemplated as I retreat, tail between my legs. – enhzflep Nov 14 '13 at 12:04
  • 1
    @イオニカ ビザウ I did not say what the result of JavaScript's `Math.pow` is, I just stated what's the **mathematical** philosophy behind it. – Sergiu Paraschiv Nov 14 '13 at 12:04
  • @SergiuParaschiv Yes, but that was discussed [in the yesterday question](http://stackoverflow.com/q/19955968/1420197). – Ionică Bizău Nov 14 '13 at 12:06
  • 1
    Specs say that if y = 0, result = 1 and x doesn't matter – Alex Nov 14 '13 at 12:28

4 Answers4

8

Your copy/paste from the documentation includes the requirement:

  • If y is +0, the result is 1, even if x is NaN

So it would seem the answer to your question is "No"

Gareth
  • 133,157
  • 36
  • 148
  • 157
6

No, there is never any situation where the result will not be run. The definition of the function states that:

  • If y is NaN, the result is NaN.
  • If y is +0, the result is 1, even if x is NaN.
  • If y is -0, the result is 1, even if x is NaN.

All arguments are coerced to numeric type before being run, so therefore no matter what it will be 1. If multiple results are applicable, the first one in order that is applicable is the result returned, which in this case is 1.

As you have said that y is 0, it is therefore not NaN, and will not return NaN as a result.

ES5 §15.8.2:

Each of the following Math object functions applies the ToNumber abstract operator to each of its arguments (in left-to-right order if there is more than one) and then performs a computation on the resulting Number value(s).

Any arguments which aren't numbers (or strings that satisfy the format of a number) will be either coerced to 0 (for null, false and ""), 1 (for true) or NaN (anything else).

Qantas 94 Heavy
  • 15,750
  • 31
  • 68
  • 83
  • Sorry, you didn't understand the question. `Math.pow(NaN, 0)` is 1. My question is if we have a value for what `Math.pow(ourValue, 0)` not to be 1. – Ionică Bizău Nov 14 '13 at 12:00
  • @イオニカビザウ: I understood the question as you had just said. My answer is **no**, it will never be not the case. – Qantas 94 Heavy Nov 14 '13 at 12:00
2

Right, since you are using node.js, which runs V8, lets have a look at the sources.

Function Math.pow is defined in math.js and states:

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

Macros TO_NUMBER_INLINE is used to cast any type to numeric value. Hence in the _MathPow operation we have numbers as arguments.

Lets move forward to hydrogen.cc, which has implementation of MathPow call that refers to HPower instruction in hydrogen-instructions.cc. The latter calculates the power using power_helper(c_left->DoubleValue(), c_right->DoubleValue()): the method defined in assembler.cc. Here we finally have the logic of the calculations:

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.
  }

  // ...
}

The comment (copied from the sources) says everything, and there is even no need to inspect power_double_int defined in the same file to say that every value passed to Math.pow as the first argument with y == 0 will return 1.

To say that definitely lets check 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;
}

From the above, n will always be 0, so while loop will never run, returning p = 1 unchanged.

VisioN
  • 143,310
  • 32
  • 282
  • 281
  • 1
    This is the correct answer! Please post the code from `power_double_int` function because that gives the answer. `unsigned n = (y < 0) ? -y : y;` sets `0` value for `n` and two lines next we have `while(n != 0) { /* do something */ } return p;` where `p` is initialized with the value `1`. So, for `y === 0`, this function returns `1`. Good! – Ionică Bizău Nov 14 '13 at 12:43
1

The first three steps of the algorithm according to the ES5 spec are as follows:

  • If y is NaN, the result is NaN.
  • If y is +0, the result is 1, even if x is NaN.
  • If y is −0, the result is 1, even if x is NaN.

If you were writing an implementation of the ES5 standard, your code would probably look something like this:

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

There is not going to be any value of x that will cause it to return anything other than 1 when y === 0.

James Allardice
  • 164,175
  • 21
  • 332
  • 312
  • Where is the source code extracted from? This seems to be the correct answer! – Ionică Bizău Nov 14 '13 at 12:09
  • I said "if you were writing an implementation... your code would probably look something like this". That's not real code from a JS engine. – James Allardice Nov 14 '13 at 12:10
  • 1
    @イオニカビザウ: what is your need for the specific implementation code? All browsers are specified to follow the invariants given in the ECMAScript language specification - all major implementations of `Math.pow()` do not behave any differently from how it is specified. If you wanted the specific code for an implementation, your question did not make that clear at all and is rather confusing as to its meaning. – Qantas 94 Heavy Nov 14 '13 at 12:58