web-dev-qa-db-fra.com

Pourquoi Math.pow () (parfois) n'est-il pas égal à ** en JavaScript?

Je viens de découvrir la fonctionnalité a**b D'ECMAScript 7 comme alternative à Math.pow(a,b) ( Référence MDN ) et est venu à travers une discussion dans cette publication , dans laquelle ils se comportent apparemment différemment. Je l'ai testé dans Chrome 55 et je peux confirmer que les résultats diffèrent.

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

tandis que

99**99 Renvoie 3.697296376497268e+197

Donc, en enregistrant la différence Math.pow(99,99) - 99**99, vous obtenez -5.311379928167671e+182.

Jusqu'ici, on pourrait dire que c'est simplement une autre implémentation, mais l'envelopper dans une fonction se comporte à nouveau différemment:

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

l'appel de diff(99) renvoie 0.

Pourquoi est-ce que ça se passe?

Comme xszaboj a souligné, ceci peut être réduit à ce problème:

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

99**99 Est évalué à la compilation ("pliage constant"), et la routine du compilateur pow est différente de la runtime one . Lors de l'évaluation de ** Au moment de l'exécution, les résultats sont identiques à Math.pow - ce n'est pas étonnant, car ** Est en réalité compilé en Math.pow appel:

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

Réellement

9999= 369729637649726772657187905628805440595668764281741102430259972423552570455277523421410650010128232727940978889548326540119429996769494359451621570193644014418071060667659301384999779999159200499899

le premier résultat est donc une meilleure approximation, mais il ne devrait pas y avoir un tel écart entre les expressions constantes et dynamiques.

Ce comportement ressemble à un bogue dans V8. Il a été rapporté et j'espère qu'il sera bientôt corrigé.

122
georg