ฉันเพิ่งศึกษาปัญหาการคำนวณจุดลอยตัวของ Java สอบถามข้อมูลที่เกี่ยวข้องจากอินเทอร์เน็ต สรุปและผ่านการเรียงลำดับและแก้ไขจุดบกพร่อง และในที่สุดก็เสร็จสิ้นบทความนี้ ทุกคนสามารถชี้ให้เห็นข้อผิดพลาดและปัญหาได้
ใน Java ตัวแปรที่ประกาศโดย float คือตัวเลขทศนิยมที่มีความแม่นยำเดียว และตัวแปรที่ประกาศโดย double คือตัวเลขทศนิยมที่มีความแม่นยำสองเท่า ตามชื่อที่แสดงถึง เอนทิตีประเภทคู่จะใช้พื้นที่หน่วยความจำสองเท่า float คือ 4 ไบต์และ double คือ 8 ไบต์ ข้อมูลแบบทศนิยมและแบบคู่ไม่สามารถแสดงผลการคำนวณได้อย่างถูกต้อง เนื่องจากการคำนวณแบบทศนิยมและแบบคู่ไม่แม่นยำ คุณสามารถดูสิ่งนี้ได้โดยใช้รหัสต่อไปนี้:
คัดลอกรหัสรหัสดังต่อไปนี้:
การทดสอบในชั้นเรียนสาธารณะ
-
โมฆะสาธารณะคง main (String [] args)
-
System.out.println(0.05 + 0.01);
System.out.println(1.0 - 0.42);
System.out.println (4.015 * 100);
System.out.println (123.3 / 100);
-
-
ผลลัพธ์ของการวิ่งคือ:
0.060000000000000005
0.5800000000000001
401.49999999999994
1.23299999999999999
เพื่อให้ได้ผลลัพธ์ที่ต้องการ เราสามารถลองใช้ java.text.DecimalFormat เพื่อจัดรูปแบบตัวเลขทศนิยม:
DecimalFormat สามารถจัดรูปแบบตัวเลขตามรูปแบบที่กำหนด อักขระการจัดรูปแบบที่ใช้กันทั่วไป ได้แก่ #, 0 เป็นต้น ตัวอย่าง:
คัดลอกรหัสรหัสดังต่อไปนี้:
System.out.println(ใหม่ java.text.DecimalFormat("0.00").format(3.125));
System.out.println(ใหม่ java.text.DecimalFormat("0.00").format(3.135));
แต่ผลลัพธ์คือ:
3.12
3.14
เนื่องจาก DecimalFormat ใช้การปัดเศษแบบครึ่งคู่ (ROUND_HALF_EVEN) พูดง่ายๆ ก็คือต้องใช้เลขคู่ที่ใกล้ที่สุดเมื่อปัดเศษเป็น 5 ดังนั้นจึงไม่สามารถรับตัวเลขทศนิยมที่เชื่อถือได้โดยใช้ DecimalForamt สุดท้ายนี้ เราสามารถใช้ BigDecimal เพื่อการคำนวณที่แม่นยำยิ่งขึ้น:
BigDecimal มีตัวสร้างหลายตัวที่เกี่ยวข้องกับตัวเลขทศนิยม:
คัดลอกรหัสรหัสดังต่อไปนี้:
BigDecimal(double val) แปล double เป็น BigDecimal
BigDecimal(String val) แปลสตริงที่แทนการส่ง BigDecimal ให้เป็น BigDecimal
อย่างไรก็ตาม การใช้พารามิเตอร์คู่เพื่อสร้างออบเจ็กต์จะส่งผลให้ค่าที่ไม่ถูกต้องแม่นยำที่สุด
ตัวอย่างเช่น:
คัดลอกรหัสรหัสดังต่อไปนี้:
BigDecimal bd1=ใหม่ BigDecimal(0.05);
System.out.println(bd1.toString());
BigDecimal bd2=ใหม่ BigDecimal("0.05");
System.out.println(bd2.toString());
รับผลลัพธ์:
0.05000000000000000277555756156289135105907917022705078125
0.05
ดังนั้นท้ายที่สุดแล้วเราจึงจำเป็นต้องใช้ String เพื่อสร้าง object เพื่อให้ผลลัพธ์ที่ได้มีความแม่นยำที่สุด นอกจากนี้ หากเป็นตัวเลขคู่ เรายังสามารถใช้: BigDecimal.valueOf(double val) เหตุผลนั้นง่ายมาก ซอร์สโค้ด JDK เป็นดังนี้:
คัดลอกรหัสรหัสดังต่อไปนี้:
สาธารณะค่า BigDecimal คงที่ (val คู่)
-
กลับ BigDecimal ใหม่ (Double.toString (val));
-
สิ่งสุดท้ายที่ควรทราบคือ การบวก การลบ การคูณ และการหารของ BigDecimal ท้ายที่สุดแล้วจะส่งกลับออบเจ็กต์ BigDecimal ใหม่ เนื่องจาก BigDecimal นั้นไม่เปลี่ยนรูป ออบเจ็กต์ใหม่จะถูกสร้างขึ้นระหว่างการดำเนินการแต่ละครั้ง ดังนั้น .add(b) แม้ว่าการดำเนินการบวก ดำเนินการแล้ว a จะไม่บันทึกค่าหลังจากการดำเนินการบวก การใช้งานที่ถูกต้องควรเป็น a=a.add(b)