Neden Math.pow () (bazen) JavaScript’te **’ye eşit değil?


118

ECMAScript 7 özelliğini ( MDN Referansı ) a**biçin bir alternatif olarak yeni keşfettim ve bu yazıda görünüşe göre farklı davrandıkları bir tartışmaya rastladım . Chrome 55'te test ettim ve sonuçların farklı olduğunu doğrulayabilirim.Math.pow(a,b)

Math.pow(99,99) İadeler 3.697296376497263e+197

buna karşılık

99**99 İadeler 3.697296376497268e+197

Yani farkın günlüğe kaydedilmesi Math.pow(99,99) - 99**99sonuçlanır -5.311379928167671e+182.

Şimdiye kadar sadece başka bir uygulama olduğu söylenebilir, ancak onu bir fonksiyona sarmak yine farklı davranır:

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

arama diff(99)dönüşleri 0.

Bu neden oluyor?

Xszaboj'un belirttiği gibi , bu, şu soruna indirgenebilir:

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

7
Görünüşe göre birisi kullandıkları algoritmayı yeniden yazmış ve kayan nokta hatası bulunmuştur. Sayılar zor ...
krillgar

4
@krillgar kulağa mantıklı geliyor, ama o zaman neden aynı hata bir işlevde olmuyor?
Thomas Altmann

3
@AndersonPimentel MDN bağlantısı bir uyumluluk tablosuna işaret ediyor .
Álvaro González

7
fark bu ikisi arasındadır: var x = 99; x * * x; ve 99 * * 99. Veya işlev diff (x) {dönüş 99 * * 99 - (x * * x); }; fark (99).
Boşluk bıraktığım

1
@xszaboj, kodu `likethis`okunabilir hale getirmek ve ayrıca kalın / italik problemden kaçınmak için ters işaretlere koydu
phuclv

Yanıtlar:


126

99**99bir derleme zamanında değerlendirilen ( "sabit katlanma") ve derleyici'nın powrutin farklıdır zamanı bir . **Çalışma zamanında değerlendirirken , sonuçlar aynıdır Math.pow- şaşılacak bir **şey yok , çünkü aslında bir çağrıya derlenmiştirMath.pow :

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

Aslında

99 99 = 36972963764972677265718790562880544059566876428174110243025997242355257045527752342141065001012823272794097888954832654011942999676949435945162157019364401441308499997767

bu nedenle ilk sonuç daha iyi bir yaklaşımdır, yine de sabit ve dinamik ifadeler arasında böyle bir tutarsızlık olmamalıdır.

Bu davranış, V8'deki bir hataya benziyor. Bu rapor edilmiştir ve umarım yakında sabit alacak.


19
Yani temelde JS'nin 99**99önceden bilgi işlemle performansı artırmaya çalışması mı? Math.powSayılar ve değişkenler için aynı çıktıyı yarattığı ve yaratmadığı için bu bir hata olarak kabul edilebilir **mi?
Thomas Altmann

3
@ThomasAltmann: Math.rowher zaman çalışma zamanıdır , const katlama yalnızca operatörler için yapılabilir. Evet, kesinlikle bir hata.
georg

11
Buradaki OP'nin görünüşüne göre bir hata günlüğe kaydedildi .
James Thorpe

5
MS Edge'i kullanıyorum ve tüm 3 sonuç aynıdır: 3.697296376497263e+197, 3.697296376497263e+197, ve 3.697296376497263e+197sırasıyla. Kesinlikle bir Chrome hatasıdır.
Nolonar

4
@ThomasAltmann, sabit katlama çalışma zamanı impl'den daha kötü bir değer üretirse , bu bir hatadır. Çalışma zamanından daha iyi bir değer üretirse, bir hata olarak kabul edilebilir veya edilmeyebilir. Bu durumda, daha iyidir - doğru değer "... 26772 ...", sabit bölme "... 268" (doğru yuvarlanmış) üretir ve çalışma zamanı "... 263" üretir (4+ son sırada birimler).
hobbs
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.