เหตุใดจึงไม่ใช้ double กับเงิน
ปัญหาความแม่นยำของเลขทศนิยมลอยตัว
เหตุใดจึงไม่ใช้ double กับเงิน เป็นบทเรียน Java Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 1 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Java Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Java Academy มีบทเรียนทั้งหมด 4 บทเรียน
ค่าเริ่มต้นที่อันตราย
การเก็บราคาไว้ใน double ดูเป็นเรื่องธรรมชาติ แต่ double ไม่สามารถแทนเศษส่วนทศนิยมส่วนใหญ่ได้อย่างแม่นยำ จึงเกิดข้อผิดพลาดเล็กน้อยที่ทำให้การคำนวณทางการเงินคลาดเคลื่อนได้
ความประหลาดใจแบบคลาสสิก
เมื่อนำ 0.1 กับ 0.2 มาบวกกันด้วย double ผลลัพธ์จะไม่ใช่ 0.3 แต่เป็นค่าที่มีข้อผิดพลาดจากการปัดเศษเล็กน้อย
public class Main {
public static void main(String[] args) {
double result = 0.1 + 0.2;
System.out.println(result);
}
}เหตุผลที่เกิดขึ้น
คอมพิวเตอร์เก็บ double ในรูปแบบเลขฐานสอง เช่นเดียวกับที่ไม่สามารถเขียนหนึ่งในสามให้ตรงทั้งหมดในรูปทศนิยมได้ ทศนิยมหลายค่า เช่น 0.1 ก็ไม่สามารถเขียนให้ตรงทั้งหมดในรูปเลขฐานสองได้เช่นกัน
ระบบจะเก็บค่าประมาณเลขฐานสองที่ใกล้เคียงที่สุดไว้ และข้อผิดพลาดจะสะสมเพิ่มขึ้น
ข้อผิดพลาดสะสมเพิ่มขึ้น
ข้อผิดพลาดเล็กน้อยเพียงครั้งเดียวอาจดูไม่สำคัญ แต่เมื่อวนซ้ำผ่านธุรกรรมนับพันรายการ ความแตกต่างจะสะสมจนกลายเป็นความผิดพลาดที่เห็นได้ชัด
public class Main {
public static void main(String[] args) {
double total = 0.0;
for (int i = 0; i < 10; i++) {
total += 0.1;
}
System.out.println(total);
}
}การเปรียบเทียบความเท่ากันที่ล้มเหลว
เนื่องจากข้อผิดพลาดจากการปัดเศษ การเปรียบเทียบค่า double ที่คำนวณแล้วด้วย == จึงมักไม่สำเร็จ ทั้งที่คุณคาดว่าค่าทั้งสองจะเท่ากัน
public class Main {
public static void main(String[] args) {
double a = 0.1 + 0.2;
double b = 0.3;
System.out.println(a == b);
}
}เงินต้องการความแม่นยำ
ในงานการเงิน ข้อผิดพลาดแม้เพียงเศษเสี้ยวของหนึ่งเซนต์ก็ยอมรับไม่ได้ ผู้ตรวจสอบบัญชีคาดหวังให้ยอดรวมตรงกันถึงระดับเซนต์
ด้วยเหตุนี้จึงไม่ควรเก็บเงินด้วยชนิดข้อมูลจุดลอยตัว
วิธีแก้ปัญหา: BigDecimal
Java มี BigDecimal ซึ่งเป็นคลาสที่เก็บตัวเลขทศนิยมได้อย่างแม่นยำ โดยแยกเก็บค่าที่ยังไม่ปรับสเกลกับมาตราส่วนออกจากกัน ดังนั้น 0.1 จึงหมายถึง 0.1 จริง ๆ
import java.math.BigDecimal;
public class Main {
public static void main(String[] args) {
BigDecimal a = new BigDecimal("0.1");
BigDecimal b = new BigDecimal("0.2");
System.out.println(a.add(b));
}
}ใช้ตัวสร้างจากสตริงเสมอ
สร้าง BigDecimal จากสตริง ไม่ใช่จาก double การส่งค่า double เข้าไปจะนำข้อผิดพลาดของเลขฐานสองติดเข้าไปใน BigDecimal ด้วย
import java.math.BigDecimal;
public class Main {
public static void main(String[] args) {
BigDecimal fromDouble = new BigDecimal(0.1);
BigDecimal fromString = new BigDecimal("0.1");
System.out.println(fromDouble);
System.out.println(fromString);
}
}หรือใช้ valueOf
BigDecimal.valueOf เป็นทางลัดที่ปลอดภัย โดยแปลงค่า double ผ่านรูปแบบสตริงมาตรฐาน จึงหลีกเลี่ยงข้อผิดพลาดของเลขฐานสองดิบได้
import java.math.BigDecimal;
public class Main {
public static void main(String[] args) {
BigDecimal price = BigDecimal.valueOf(19.99);
System.out.println(price);
}
}การเก็บเงินในหน่วยเซนต์
อีกทางเลือกหนึ่งสำหรับกรณีง่าย ๆ คือเก็บเงินเป็นจำนวนเต็มของหน่วยเซนต์โดยใช้ long จากนั้น 19.99 ดอลลาร์จะกลายเป็น 1999 เซนต์ และการคำนวณทั้งหมดจะเป็นการคำนวณจำนวนเต็มที่แม่นยำ
public class Main {
public static void main(String[] args) {
long cents = 1999;
long total = cents * 3;
System.out.println(total + " cents");
}
}ข้อสรุปสำคัญ
ใช้ float และ double กับงานวิทยาศาสตร์และงานกราฟิกที่ยอมรับข้อผิดพลาดเล็กน้อยได้ สำหรับเงินและค่าทุกชนิดที่ต้องแม่นยำ ให้ใช้ BigDecimal หรือจำนวนเต็มในหน่วยเซนต์
ตรวจสอบอย่างรวดเร็ว
ทดสอบความเข้าใจเกี่ยวกับความแม่นยำของเลขจุดลอยตัว
ทบทวน
คุณได้เรียนรู้ว่าเหตุใด double จึงไม่เหมาะกับการเก็บเงิน:
- เลขจุดลอยตัวฐานสองไม่สามารถเก็บทศนิยมหลายค่าได้อย่างแม่นยำ
- ข้อผิดพลาดอย่าง
0.1 + 0.2ที่ไม่เท่ากับ 0.3 จะสะสมเพิ่มขึ้น - ใช้
BigDecimalสำหรับการคำนวณทศนิยมที่ต้องการความแม่นยำ - สร้างจากสตริงหรือใช้
valueOfแทนการสร้างจาก double ดิบเสมอ - การเก็บเป็นจำนวนเต็มในหน่วยเซนต์ก็เป็นอีกทางเลือกที่แม่นยำ
คำถามที่พบบ่อย
บทเรียน “เหตุใดจึงไม่ใช้ double กับเงิน” ฟรีหรือไม่
ใช่ — ข้อความเต็มของ “เหตุใดจึงไม่ใช้ double กับเงิน” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Java Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Java Academy มีบทเรียนทั้งหมด 4 บทเรียน
คุณจะเรียนรู้อะไรในบทเรียน “เหตุใดจึงไม่ใช้ double กับเงิน”
ปัญหาความแม่นยำของเลขทศนิยมลอยตัว คุณปฏิบัติ Java Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน
คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Java Academy หรือไม่
ไม่จำเป็นต้องมีประสบการณ์มาก่อน Java Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 1 จากทั้งหมด 4 บทเรียน
บทเรียน “เหตุใดจึงไม่ใช้ double กับเงิน” ใช้เวลานานแค่ไหน
บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย
ฉันเขียนและรันโค้ดในบทเรียน Java Academy นี้ได้ไหม
ได้ บทเรียน Java Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- เหตุใดจึงไม่ใช้ double กับเงิน
- การทำงานกับ BigDecimal
- การปัดเศษและสเกล
- BigInteger สำหรับตัวเลขขนาดใหญ่