0Pricing
Java Academy · บทเรียน

เหตุใดจึงไม่ใช้ 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 ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

บทเรียนทั้งหมดในหลักสูตรนี้

  1. เหตุใดจึงไม่ใช้ double กับเงิน
  2. การทำงานกับ BigDecimal
  3. การปัดเศษและสเกล
  4. BigInteger สำหรับตัวเลขขนาดใหญ่
← กลับไปที่ Java Academy