เหตุใด Math.pow () (บางครั้ง) จึงไม่เท่ากับ ** ใน JavaScript


118

ฉันเพิ่งค้นพบคุณลักษณะ ECMAScript 7 a**bเป็นทางเลือกสำหรับMath.pow(a,b)( อ้างอิง MDN ) และพบการสนทนาในโพสต์นั้นซึ่งเห็นได้ชัดว่าพวกเขาทำงานแตกต่างกัน ฉันได้ทดสอบใน Chrome 55 และสามารถยืนยันได้ว่าผลลัพธ์แตกต่างกัน

Math.pow(99,99) ผลตอบแทน 3.697296376497263e+197

แต่ทว่า

99**99 ผลตอบแทน 3.697296376497268e+197

ดังนั้นการเข้าสู่ระบบความแตกต่างของผลในการMath.pow(99,99) - 99**99-5.311379928167671e+182

จนถึงตอนนี้อาจกล่าวได้ว่าเป็นเพียงการนำไปใช้งานอื่น แต่การรวมไว้ในฟังก์ชั่นจะทำงานแตกต่างกันอีกครั้ง:

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

เรียกร้องผลตอบแทนdiff(99)0

เหตุใดจึงเกิดขึ้น

ดังที่xszabojชี้ให้เห็นปัญหานี้สามารถ จำกัด ให้แคบลงได้:

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

7
ดูเหมือนว่ามีคนเขียนอัลกอริทึมที่พวกเขาใช้ใหม่และพบข้อผิดพลาดทศนิยม ตัวเลขยาก ...
krillgar

4
@krillgar ฟังดูสมเหตุสมผล แต่เหตุใดจึงไม่เกิดข้อผิดพลาดเดียวกันในฟังก์ชัน
Thomas Altmann

3
@AndersonPimentel MDN เชื่อมโยงจุดไปยังตารางการทำงานร่วมกัน
ÁlvaroGonzález

7
ความแตกต่างระหว่างสองสิ่งนี้: var x = 99; x * * x; และ 99 * * 99 หรือฟังก์ชัน diff (x) {return 99 * * 99 - (x * * x); }; diff (99) ขออภัยในการเว้นวรรคความคิดเห็นกรองสองดาว :(
xszaboj

1
@xszaboj ใส่โค้ดลงใน backticks `likethis`เพื่อให้อ่านได้และหลีกเลี่ยงปัญหาตัวหนา / ตัวเอียง
phuclv

คำตอบ:


126

99**99มีการประเมินที่รวบรวมเวลา ( "พับอย่างต่อเนื่อง") และคอมไพเลอร์ของpowกิจวัตรประจำวันจะแตกต่างจากหนึ่งรันไทม์ เมื่อประเมิน**ในขณะดำเนินการผลลัพธ์จะเหมือนกันMath.pow- ไม่น่าแปลกใจเนื่องจาก**ถูกรวบรวมไปยังการMath.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

แท้จริง

99 99 = 3697296376497267726571879056288054405956687642817411024302599724235525704552775234214106500101282327279409788895483265401194299967694943594516215701936440144180710996066765965984401441807109960667654401441807109960667659659401441807

ดังนั้นผลลัพธ์แรกคือการประมาณที่ดีกว่า แต่ก็ยังไม่ควรเกิดความคลาดเคลื่อนระหว่างนิพจน์คงที่และไดนามิก

ลักษณะการทำงานนี้ดูเหมือนบั๊กใน V8 มันได้รับการรายงานและหวังว่าจะได้รับการแก้ไขในเร็ว ๆ นี้


19
ดังนั้นโดยพื้นฐานแล้ว JS พยายามปรับปรุงประสิทธิภาพด้วยการประมวลผล99**99ล่วงหน้าหรือไม่? นี่อาจถือเป็นจุดบกพร่องหรือไม่เนื่องจากMath.powสร้างผลลัพธ์เดียวกันสำหรับตัวเลขและตัวแปรและ**ไม่
Thomas Altmann

3
@ThomasAltmann: Math.rowเป็นรันไทม์เสมอการพับ const สามารถทำได้สำหรับตัวดำเนินการเท่านั้น ใช่บั๊กแน่ ๆ
จอร์เจีย

11
มีการบันทึกข้อผิดพลาดโดยรูปลักษณ์ของสิ่งต่างๆโดย OP ที่นี่
James Thorpe

5
ฉันใช้ MS ขอบและ 3 ผลเหมือนกันทั้งหมด: 3.697296376497263e+197, 3.697296376497263e+197และ3.697296376497263e+197ตามลำดับ เป็นบั๊กของ Chrome อย่างแน่นอนที่สุด
Nolonar

4
@ThomasAltmann ถ้าการพับแบบคงที่ให้ค่าที่แย่กว่า runtime im แสดงว่าเป็นบั๊ก หากสร้างค่าที่ดีกว่ารันไทม์แสดงว่าอาจถือเป็นข้อบกพร่องหรือไม่ก็ได้ ในกรณีนี้จะดีกว่า - ค่าที่ถูกต้องคือ "... 26772 ... " การพับแบบคงที่จะสร้าง "... 268" (ปัดเศษอย่างถูกต้อง) และรันไทม์จะสร้าง "... 263" (ปิดด้วย 4+ หน่วยในสถานที่สุดท้าย)
hobbs
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.