Why is Math.pow() (sometimes) not equal to ** in JavaScript?

JavascriptGoogle ChromeV8Ecmascript 2016

Javascript Problem Overview


I've just discovered the ECMAScript 7 feature a**b as an alternative for Math.pow(a,b) (MDN Reference) and came across a discussion in that post, in which they apparently behave differently. I've tested it in Chrome 55 and can confirm that the results differ.

Math.pow(99,99) returns 3.697296376497263e+197

whereas

99**99 returns 3.697296376497268e+197

So logging the difference Math.pow(99,99) - 99**99 results in -5.311379928167671e+182.

So far it could be said, that it's simply another implementation, but wrapping it in a function behaves different again:

function diff(x) {
  return Math.pow(x,x) - x**x;
}

calling diff(99) returns 0.

Why is that happening?

As xszaboj pointed out, this can be narrowed down to this problem:

var x = 99;
x**x - 99**99; // Returns -5.311379928167671e+182

Javascript Solutions


Solution 1 - Javascript

99**99 is evaluated at compile time ("constant folding"), and the compiler's pow routine is different from the runtime one. When evaluating ** at run time, results are identical with Math.pow — no wonder since ** is actually compiled to a Math.pow call:

console.log(99**99);           // 3.697296376497268e+197
a = 99, b = 99;
console.log(a**b);             // 3.697296376497263e+197
console.log(Math.pow(99, 99)); // 3.697296376497263e+197

Actually

9999=369729637649726772657187905628805440595668764281741102430259972423552570455277523421410650010128232727940978889548326540119429996769494359451621570193644014418071060667659301384999779999159200499899

so the first result is a better approximation, still such a discrepancy between constant- and dynamic expressions shouldn't take place.

This behavior looks like a bug in V8. It has been reported and will hopefully get fixed soon.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionThomas AltmannView Question on Stackoverflow
Solution 1 - JavascriptgeorgView Answer on Stackoverflow