คำนวณทศนิยมขนาดใหญ่ (มากกว่า 15 หลัก) ใน Javascript

ดังที่เราทราบ Javascript มีปัญหา (หรือคุณสมบัติ) บางประการในการคำนวณเลขทศนิยม ตัวอย่างเช่น:

console.log(0.1 + 0.2) // 0.30000000000000004

และเรารู้ว่าเราสามารถหลีกเลี่ยงได้โดยใช้ไลบรารีต่างๆ (เช่น ฉันใช้ bignumber.js ) และตอนนี้เราก็ได้สิ่งที่คาดหวังแล้ว:

console.log(Number(new BigNumber(0.1).plus(0.2))); // 0.3
<script src="https://cdnjs.cloudflare.com/ajax/libs/bignumber.js/6.0.0/bignumber.min.js"></script>

แต่

Bignumber.js มีข้อจำกัด:

ยอมรับค่าประเภทตัวเลข (สูงสุด 15 หลักสำคัญเท่านั้น) สตริงหรืออ็อบเจ็กต์ BigNumber

เราสามารถส่งผ่านสตริงได้ (เป็นไปได้) แต่วิธีนี้จะทำให้ตัวเลขบางส่วนหายไปจากจุดสิ้นสุด:

console.log(Number(new BigNumber(0.1).plus("198.43092534959501"))); // 198.530925349595, not 198.53092534959501
<script src="https://cdnjs.cloudflare.com/ajax/libs/bignumber.js/6.0.0/bignumber.min.js"></script>

ตอนนี้ฉันทำงานกับสกุลเงินดิจิทัล และบ่อยครั้งที่ฉันจัดการกับตัวเลขเช่น 198.43092534959501 และในกรณีนี้ ฉันได้รับข้อผิดพลาด (ตามที่คาดไว้):

console.log(Number(new BigNumber(0.1).plus(198.43092534959501))); // error
<script src="https://cdnjs.cloudflare.com/ajax/libs/bignumber.js/6.0.0/bignumber.min.js"></script>

ฉันรู้ว่าบางคนใช้ตัวคูณเพิ่มเติม แต่จะไม่ทำงานในกรณีที่ระบุไว้ข้างต้น หากคุณจัดการกับสกุลเงินดิจิทัล คุณจะรู้ว่าจริงๆ แล้วเราใช้งานได้กับค่าที่ไม่คูณและคูณ (เช่น 489964999999000000 และ 0.489964999999) แต่เป้าหมายของฉันในตอนนี้คือการรวมยอดคงเหลือคำสั่งทั้งหมดสำหรับสกุลเงินที่แตกต่างกัน แต่มีตัวคูณที่แตกต่างกัน ดังนั้นฉันจึงไม่สามารถรวมค่าที่ไม่คูณได้ และดูเหมือนว่าฉันต้องรวมค่าที่คูณด้วยวิธีใดวิธีหนึ่ง

มันเป็นพื้นหลังเล็กๆ แต่ คำถามทั่วไปของฉันคือ:

วิธีบวก/คูณ/อื่นๆ เลขฐานสิบซึ่งมีมากกว่า 15 หลัก?


person Commercial Suicide    schedule 03.04.2018    source แหล่งที่มา
comment
ฉันคิดว่าคุณตอบคำถามของคุณเองในเบื้องหลัง มันบอกว่า BigNumber จะยอมรับตัวเลขที่จัดรูปแบบเป็นสตริงเป็นอินพุต   -  person nbering    schedule 03.04.2018
comment
0.1 ไม่ใช่ตัวเลขทศนิยม แต่เป็นชนิดข้อมูลจุดลอยตัว และประเภทข้อมูลจุดลอยตัวเหล่านั้นไม่เหมาะสำหรับการคำนวณทศนิยมเนื่องจากมีวัตถุประสงค์ที่แตกต่างกัน และนั่นไม่ใช่เฉพาะกรณีของ JS เท่านั้น แต่ยังรวมถึงภาษาอื่นด้วย   -  person t.niese    schedule 03.04.2018


คำตอบ (1)


ฉันตอบไปแล้วในความคิดเห็น แต่นี่คือการสาธิต BigNumber จะยอมรับตัวเลขในรูปแบบสตริงสำหรับการป้อนข้อมูล

console.log(new BigNumber(0.1).plus("198.43092534959501"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/bignumber.js/6.0.0/bignumber.min.js"></script>

person nbering    schedule 03.04.2018
comment
ใช่ ได้ผล ขอบคุณ แต่ในกรณีนี้ตัวเลข 2 หลักสุดท้ายจะหายไป มีวิธีเก็บเลขให้ครบมั้ย? - person Commercial Suicide; 03.04.2018
comment
อย่าแปลงกลับเป็น Number และคุณเก็บตัวเลขจำนวนเท่าใดก็ได้ที่คุณได้กำหนดค่า BigDecimal ไว้ใช้ใช่ไหม - person Scott Sauyet; 03.04.2018
comment
ฉันได้อัปเดตคำตอบแล้ว ตัวเลขสุดท้ายหายไปเนื่องจากตัวอย่างของคุณโยนกลับเป็นตัวเลข เพียงเก็บตัวเลขเป็นสตริงหรือ BigNumber ไว้ตลอดเวลา - person nbering; 03.04.2018
comment
คำตอบที่ดี ขอบคุณ (และถึง @ScottSauyet ด้วย)! ฉันหวังว่าเราจะทำได้กับตัวเลข แต่ถ้าไม่ได้ ไม่เป็นไร ฉันจะปรับตัว ขอบคุณอีกครั้ง! - person Commercial Suicide; 03.04.2018
comment
ไม่มีทางที่จะรักษาระดับความแม่นยำนี้ใน JavaScript ได้ จำนวนความละเอียดบิตรวมอยู่ในข้อกำหนดภาษา ดังนั้นไลบรารีจึงจำเป็นต้องจัดการกับสิ่งที่มีขนาดใหญ่ขนาดนี้ ฉันพยายามดิ้นรนกับสิ่งเดียวกันในขณะที่เล่นกับรูปแบบไฟล์ crypto-key ใน NodeJS - person nbering; 03.04.2018
comment
มันไม่สมเหตุสมผลเลยที่จะทำกับตัวเลข หาก JS Numbers สามารถจัดการสิ่งนี้ได้ ก็ไม่จำเป็นต้องใช้ไลบรารี BigNumber หรือไลบรารีที่คล้ายกัน - person Scott Sauyet; 03.04.2018
comment
@ScottSauyet ขอบคุณคำแนะนำที่ดี แนวคิดหลักชัดเจนมากขึ้นสำหรับฉันตอนนี้ - person Commercial Suicide; 03.04.2018