1. การปัดเศษจำนวนจริง

ดังที่เราได้กล่าวไปแล้ว เมื่อมีการกำหนดจำนวนจริงให้กับintตัวแปร มันจะถูกปัดเศษลงเป็นจำนวนเต็มที่น้อยกว่าที่ใกล้ที่สุดเสมอ — ส่วนที่เป็นเศษส่วนนั้นจะถูกปัดทิ้งไป

แต่เป็นเรื่องง่ายที่จะจินตนาการถึงสถานการณ์เมื่อจำนวนเศษส่วนจำเป็นต้องถูกปัดเศษเป็นจำนวนเต็มที่ใกล้เคียงที่สุดในทิศทางใดทิศทางหนึ่ง หรือแม้แต่ปัดขึ้น คุณจะทำอย่างไรในกรณีนี้?

สำหรับสิ่งนี้และสำหรับสถานการณ์ที่คล้ายกัน Java มีMathคลาสซึ่งมีround(), ceil(), และfloor()เมธอด


Math.round()วิธี

วิธีMath.round()การปัดตัวเลขให้เป็นจำนวนเต็มที่ใกล้เคียงที่สุด:

long x = Math.round(real_number)

แต่มีความแตกต่างกันเล็กน้อยที่นี่: วิธีนี้ส่งคืนจำนวนเต็มlong(ไม่ใช่ an int) เนื่องจากจำนวนจริงอาจมีขนาดใหญ่มาก ผู้สร้าง Java จึงตัดสินใจใช้ประเภทจำนวนเต็มที่ใหญ่ที่สุดที่มีของ Java long:

ดังนั้น หากโปรแกรมเมอร์ต้องการกำหนดผลลัพธ์ให้กับintตัวแปร เธอจะต้องระบุอย่างชัดเจนต่อคอมไพเลอร์ว่าเธอยอมรับการสูญเสียข้อมูลที่เป็นไปได้ (ในกรณีที่ตัวเลขผลลัพธ์ไม่ตรงกับประเภทint)

int x = (int) Math.round(real_number)

ตัวอย่าง:

คำแถลง ผลลัพธ์
int x = (int) Math.round(4.1);
4
int x = (int) Math.round(4.5);
5
int x = (int) Math.round(4.9);
5

Math.ceil()วิธี

วิธีMath.ceil()การปัดตัวเลขขึ้นเป็นจำนวนเต็ม นี่คือตัวอย่าง:

คำแถลง ผลลัพธ์
int x = (int) Math.ceil(4.1);
5
int x = (int) Math.ceil(4.5);
5
int x = (int) Math.ceil(4.9);
5

Math.floor()วิธี

วิธีMath.floor()การปัดตัวเลขลงเป็นจำนวนเต็ม นี่คือตัวอย่าง:

คำแถลง ผลลัพธ์
int x = (int) Math.floor(4.1);
4
int x = (int) Math.floor(4.5);
4
int x = (int) Math.floor(4.9);
4

แน่นอน เมื่อปัดเศษตัวเลขเป็นจำนวนเต็ม การใช้ตัวดำเนินการประเภทการโยนจะง่ายกว่า:(int)

คำแถลง ผลลัพธ์
int x = (int) 4.9
4

หากคุณจำชื่อเหล่านี้ได้ยาก บทเรียนภาษาอังกฤษสั้นๆ จะช่วยได้:

  • Mathหมายถึงคณิตศาสตร์
  • Roundแปลว่า รอบ
  • Ceilingหมายถึงเพดาน
  • Floorหมายถึงพื้น

2. จำนวนทศนิยมมีโครงสร้างอย่างไร

ประเภท สามารถเก็บ ค่าdoubleในช่วงจากถึง ช่วงของค่าจำนวนมาก (เมื่อเทียบกับประเภท) อธิบายได้จากข้อเท็จจริงที่ว่าประเภท (รวมถึง) มีโครงสร้างภายในที่แตกต่างอย่างสิ้นเชิงกับประเภทจำนวนเต็ม ภายในประเภทจะเข้ารหัสค่าเป็นตัวเลขสองตัว: ตัวแรกเรียกว่าแมนทิสซาและตัวที่สองเรียกว่าเลขชี้กำลัง-1.7*10308+1.7*10308intdoublefloatdouble

สมมติว่าเรามีตัวเลข123456789และเก็บเป็นdoubleตัวแปร เมื่อเราทำเช่น นั้นตัวเลขจะถูกแปลงเป็นและภายในประเภทจะเก็บตัวเลขสองตัว — และ เครื่องหมายซิกนิฟิแคนด์ ("ส่วนสำคัญของตัวเลข" หรือแมนทิสซา) จะถูกเน้นด้วยสีแดง ในขณะที่เลขชี้กำลังจะถูกเน้นด้วยสีน้ำเงิน1.23456789*108double234567898

วิธีการนี้ทำให้สามารถจัดเก็บได้ทั้งตัวเลขที่มากและมีขนาดเล็กมาก แต่เนื่องจากการแสดงตัวเลขจำกัดไว้ที่ 8 ไบต์ (64 บิต )และบางบิตถูกใช้เพื่อเก็บเลขชี้กำลังคือ15 _

นี่เป็น คำอธิบาย ที่ง่าย มาก ว่าจำนวนจริงมีโครงสร้างอย่างไร


3. สูญเสียความแม่นยำเมื่อทำงานกับจำนวนจริง

เมื่อทำงานกับจำนวนจริง โปรดจำไว้เสมอว่าจำนวนจริง ไม่แน่นอน อาจมีข้อผิดพลาดในการปัดเศษและข้อผิดพลาดในการแปลง เสมอ เมื่อแปลงจากเลขฐานสิบเป็นเลขฐานสอง นอกจากนี้ ข้อผิดพลาดที่พบได้บ่อยที่สุดคือการสูญเสียความแม่นยำเมื่อบวก/ลบตัวเลขในมาตราส่วนที่แตกต่างกันอย่างสิ้นเชิง

ข้อเท็จจริงสุดท้ายนี้เป็นเรื่องที่น่าเหลือเชื่อสำหรับโปรแกรมเมอร์มือใหม่

ถ้าเราลบออกจากเราจะได้1/109109109

การลบตัวเลขในระดับที่แตกต่างกันอย่างสิ้นเชิง คำอธิบาย
 1000000000.000000000;
-         0.000000001;
 1000000000.000000000;
จำนวนที่สองมีขนาดเล็กมากซึ่งจะทำให้ไม่มีนัยสำคัญ (เน้นด้วยสีเทา) ตัวเลขนัยสำคัญ 15 หลักจะถูกเน้นด้วยสีส้ม

เราสามารถพูดอะไรได้บ้าง การเขียนโปรแกรมไม่เหมือนกับคณิตศาสตร์


4. ข้อผิดพลาดเมื่อเปรียบเทียบจำนวนจริง

อันตรายอีกประการหนึ่งคือการรอโปรแกรมเมอร์เมื่อพวกเขาเปรียบเทียบจำนวนจริง เกิดขึ้นเมื่อทำงานกับจำนวนจริง เนื่องจากข้อผิดพลาดในการปัดเศษสามารถสะสมได้ ผลลัพธ์คือมีบางสถานการณ์ที่คาดว่าจำนวนจริงจะเท่ากัน แต่ก็ไม่เป็นเช่นนั้น หรือกลับกัน: คาดว่าตัวเลขจะต่างกัน แต่ก็เท่ากัน

ตัวอย่าง:

คำแถลง คำอธิบาย
double a = 1000000000.0;
double b = 0.000000001;
double c = a - b;
ค่าของตัวแปรa จะเป็น1000000000.0
ค่าของตัวแปรc จะเป็น1000000000.0
(ตัวเลขในb ตัวแปรน้อยเกินไป)

ในตัวอย่างข้างต้นaและcไม่ควรเท่ากัน แต่จะมี

หรือลองมาอีกตัวอย่างหนึ่ง:

คำแถลง คำอธิบาย
double a = 1.00000000000000001;
double b = 1.00000000000000002;
ค่าของตัวแปรa จะเป็น1.0
ค่าของตัวแปรb จะเป็น1.0

5. ข้อเท็จจริงที่น่าสนใจเกี่ยวกับstrictfp

Java มีstrictfpคีย์เวิร์ดพิเศษ ( เข้มงวด f loating p oint ) ซึ่งไม่พบในภาษาโปรแกรมอื่น และคุณรู้หรือไม่ว่าทำไมคุณถึงต้องการมัน? มันทำให้ความแม่นยำของการดำเนินการแย่ลงด้วยตัวเลขทศนิยม นี่คือเรื่องราวของความเป็นมา:

ผู้สร้าง Java:
เราต้องการให้ Java เป็นที่นิยมอย่างมากและเรียกใช้โปรแกรม Java บนอุปกรณ์ต่างๆ ให้ได้มากที่สุด ดังนั้นเราจึงตรวจสอบให้แน่ใจว่าข้อกำหนดของเครื่อง Java ระบุว่าโปรแกรมทั้งหมดต้องทำงานในลักษณะเดียวกันบนอุปกรณ์ทุกประเภท!
ผู้ผลิตโปรเซสเซอร์ Intel:
เฮ้ทุกคน! เราได้ปรับปรุงตัวประมวลผลของเรา และตอนนี้จำนวนจริงทั้งหมดจะแสดงโดยใช้ 10 ไบต์แทน 8 ไบต์ภายในตัวประมวลผลของเรา จำนวนไบต์ที่มากขึ้นหมายถึงตัวเลขที่มีนัยสำคัญมากขึ้น นั่นหมายความว่าอย่างไร? ถูกตัอง! ตอนนี้การคำนวณทางวิทยาศาสตร์ของคุณจะแม่นยำยิ่งขึ้น!
นักวิทยาศาสตร์และทุกคนที่เกี่ยวข้องกับการคำนวณที่แม่นยำเป็นพิเศษ:
เย็น! ทำได้ดี. ข่าวดี!
ผู้สร้าง Java:
ไม่ไม่ไม่พวกคุณ! เราบอกคุณแล้วว่าโปรแกรม Java ทั้งหมดต้องทำงานเหมือนกันในทุกอุปกรณ์ . เราจะบังคับให้ใช้จำนวนจริง 10 ไบต์ภายในโปรเซสเซอร์ Intel
ตอนนี้ทุกอย่างเรียบร้อยดีอีกครั้ง! ไม่ต้องขอบคุณเรา
นักวิทยาศาสตร์และทุกคนที่เกี่ยวข้องกับการคำนวณที่แม่นยำเป็นพิเศษ:
คุณบ้าไปแล้วหรือเปล่า? ให้ทุกอย่างกลับมาเหมือนเดิมโดยเร็ว!
ผู้สร้าง Java:
พวกนี้เพื่อประโยชน์ของคุณเอง! ลองนึกภาพดู: โปรแกรม Java ทั้งหมดทำงานในลักษณะเดียวกันบนอุปกรณ์ทั้งหมด มันเจ๋งมาก!
นักวิทยาศาสตร์และทุกคนที่เกี่ยวข้องกับการคำนวณที่แม่นยำเป็นพิเศษ:
ไม่ มันไม่เจ๋งเลย ทำให้ทุกอย่างกลับมาเหมือนเดิมอย่างรวดเร็ว! หรือรู้ว่าเราจะวาง Java ของคุณไว้ที่ใด
ผู้สร้าง Java:
อืม. ทำไมคุณไม่พูดทันที แน่นอนเราจะใส่กลับ
เราคืนความสามารถให้คุณใช้คุณสมบัติทั้งหมดของโปรเซสเซอร์ล่าสุด
อย่างไรก็ตาม... เรายังเพิ่มstrictfpคำหลักในภาษานั้น เป็นพิเศษอีกด้วย หากคุณเขียนก่อนชื่อฟังก์ชัน การดำเนินการทั้งหมดที่เกี่ยวข้องกับจำนวนจริงภายในฟังก์ชันนั้นจะแย่พอๆ กันในทุกอุปกรณ์ !