จำนวนจุดลอยตัว

ในทางคอมพิวเตอร์ จำนวนจุดลอยตัว (แม่แบบ:Langx) คือระบบแทนจำนวนชนิดหนึ่ง ซึ่งจำนวนนั้นอาจมีขนาดใหญ่หรือขนาดเล็กเกินกว่าที่จะแทนด้วยจำนวนเต็ม เนื่องจากจำนวนต่าง ๆ สามารถเขียนแทนด้วยเลขนัยสำคัญ (mantissa) จำนวนหนึ่งโดยประมาณ และเปลี่ยนสเกลด้วยเลขชี้กำลัง (exponent) ฐานของสเกลปกติจะเป็น 2, 10 หรือ 16 เป็นต้น จำนวนทั่วไปจึงสามารถเขียนให้อยู่ในรูปแบบนี้ได้
- เลขนัยสำคัญ × ฐาน เลขชี้กำลัง
คำว่า จุดลอยตัว จึงหมายถึงจุดฐาน (จุดทศนิยม หรือในคอมพิวเตอร์คือ จุดทวินิยม[1]) ที่สามารถ "ลอยตัว" ได้ หมายความว่า จุดฐานสามารถวางไว้ที่ตำแหน่งใดก็ได้ที่สัมพันธ์กับเลขนัยสำคัญของจำนวนนั้น ตำแหน่งนี้แสดงไว้แยกต่างหากในข้อมูลภายใน และการแทนด้วยจำนวนจุดลอยตัวจึงอาจถือว่าเป็นสัญกรณ์วิทยาศาสตร์ในบริบทของคอมพิวเตอร์ หลายปีที่ผ่านมา คอมพิวเตอร์ใช้งานจำนวนจุดลอยตัวในรูปแบบที่แตกต่างกัน เวลาต่อมาจึงทำให้เกิดมาตรฐาน IEEE 754 สำหรับจำนวนที่พบได้อย่างปกติสามัญชนิดนี้
ข้อดีของจำนวนจุดลอยตัวที่มีต่อจำนวนจุดตรึง (fixed point รวมทั้งจำนวนเต็ม) คือจำนวนจุดลอยตัวสามารถรองรับค่าได้ในขอบเขตที่กว้างกว่า ตัวอย่างเช่น จำนวนจุดตรึงที่มีตัวเลขเจ็ดหลัก และกำหนดให้สองหลักสุดท้ายอยู่หลังจุด สามารถแทนจำนวนเหล่านี้ได้ 12345.67, 123.45, 1.23 ในขณะที่จำนวนจุดลอยตัว (ตามเลขฐานสิบของมาตรฐาน IEEE 754) ที่มีตัวเลขเจ็ดหลักเช่นกัน สามารถแทนจำนวนเหล่านี้ได้อีกเพิ่มเติม 1.234567, 123456.7, 0.00001234567, 1234567000000000 เป็นต้น แต่ข้อเสียคือรูปแบบของจำนวนจุดลอยตัวจำเป็นต้องใช้หน่วยเก็บข้อมูลมากขึ้นอีกเล็กน้อย (สำหรับเข้ารหัสตำแหน่งของจุดฐาน) ดังนั้นเมื่อจำนวนทั้งสองประเภทเก็บบันทึกอยู่ในที่ที่เหมือนกัน จำนวนจุดลอยตัวจะใช้เนื้อที่มากกว่าเพื่อเพิ่มความเที่ยง (precision)
ความเร็วของการดำเนินการกับจำนวนจุดลอยตัว เป็นการวัดประสิทธิภาพของคอมพิวเตอร์อย่างหนึ่งที่สำคัญในขอบเขตข่ายโปรแกรมประยุกต์ ซึ่งมีหน่วยวัดเป็นฟล็อปส์ (FLOPS - floating-point operations per second การประมวลผลจุดลอยตัวต่อวินาที)
ภาพรวม
การแทนจำนวน (หรือเรียกว่าระบบเลขในคณิตศาสตร์) เป็นการกำหนดวิธีการเก็บบันทึกจำนวนหนึ่ง ๆ ที่อาจถูกเข้ารหัสให้เป็นสายอักขระของเลขโดด เลขคณิตของจำนวนถูกนิยามให้เป็นกลุ่มของการปฏิบัติกับรูปแบบนั้น ซึ่งเป็นการจำลองการดำเนินการทางเลขคณิตแบบดั้งเดิม
มีกลไกหลายประเภทที่ใช้สายอักขระของเลขโดดแทนจำนวน ในสัญกรณ์คณิตศาสตร์ทั่วไป สายอักขระของเลขโดดสามารถยาวเท่าใดก็ได้ และตำแหน่งของจุดฐานแสดงไว้โดยการใส่จุดทศนิยม (ซึ่งอาจเป็นมหัพภาคหรือจุลภาค) ไว้ตรงนั้น ถ้าจุดฐานไม่ปรากฏ จะถูกสมมติโดยนัยว่าวางอยู่ทางขวาสุด (นัยสำคัญน้อยสุด) ของสายอักขระของเลขโดด (นั่นคือจำนวนนั้นเป็นจำนวนเต็ม) ในระบบจำนวนจุดตรึง สมมติฐานบางข้อถูกกำหนดขึ้นว่าจุดฐานจะอยู่ที่ตำแหน่งใดของสายอักขระ ตัวอย่างเช่น ข้อตกลงเกิดขึ้นว่าสายอักขระประกอบด้วยเลขโดดฐานสิบ แปดหลัก โดยมีจุดทศนิยมอยู่ตรงกลาง ดังนั้นจำนวน "00012345" จึงหมายถึงค่า 1.2345
ในสัญกรณ์วิทยาศาสตร์ จำนวนที่กำหนดจะเปลี่ยนสเกลด้วยกำลังของ 10 ดังนั้นเลขนัยสำคัญจึงมีค่าอยู่ในช่วงจำเพาะคืออยู่ระหว่าง 1 ถึง 10 โดยจุดฐานจะปรากฏถัดจากเลขโดดตัวแรกทันที ตัวคูณสเกลที่เป็นกำลังของ 10 จะแสดงแยกต่างหากไปที่ท้ายจำนวน ตัวอย่างเช่น เวลาที่ใช้ในการหมุนรอบตัวเองของดวงจันทร์ไอโอของดาวพฤหัสบดีเท่ากับ 152853.5047 วินาที จำนวนนี้สามารถแสดงได้ในสัญกรณ์คณิตศาสตร์รูปแบบมาตรฐานเป็น 1.528535047แม่แบบ:E วินาที
จำนวนจุดลอยตัวเป็นแนวคิดที่คล้ายกับสัญกรณ์คณิตศาสตร์ จึงประกอบด้วยสองส่วนตามหลักเหตุผล
- สายอักขระของเลขโดดที่มีเครื่องหมายบวกลบ ตามความยาวและฐานที่กำหนด ส่วนนี้เรียกว่า ซิกนิฟิแคนด์ (significand) หรือบางครั้งเรียกว่า แมนทิสซา (mantissa) หรือ สัมประสิทธิ์ จุดฐานนั้นไม่ได้รวมอยู่ด้วย แต่อาจสมมติโดยนัยว่าวางอยู่ที่ใดที่หนึ่งในซิกนิฟิแคนด์ ซึ่งบ่อยครั้งอยู่ก่อนหรือหลังเลขโดดที่มีนัยสำคัญมากสุด หรืออยู่ทางขวาสุดก็ได้ (บทความนี้จะใช้ข้อตกลงว่าจุดฐานอยู่หลังเลขโดดที่มีนัยสำคัญมากสุด) ความยาวของซิกนิฟิแคนด์เป็นตัวพิจารณาความเที่ยงของจำนวนที่ใช้แทน
- เลขชี้กำลังจำนวนเต็มที่มีเครื่องหมายบวกลบ หรือเรียกว่า แคแรกเทอริสติก (characteristic) หรือสเกล ซึ่งเป็นตัวดัดแปรขนาดมากน้อยของจำนวน
ซิกนิฟิแคนด์ คูณด้วย ฐาน ที่ยกกำลังด้วย เลขชี้กำลัง จะเทียบเท่ากับการเลื่อนจุดฐานจากตำแหน่งสมมติ ไปเป็นจำนวนหลักเท่ากับค่าของเลขชี้กำลัง โดยเลื่อนไปทางขวาถ้าเลขชี้กำลังเป็นบวกหรือไปทางซ้ายถ้าเลขชี้กำลังเป็นลบ
หากอธิบายด้วยเลขฐานสิบอันเป็นสัญกรณ์ที่คุ้นเคย จำนวน 152853.5047 ซึ่งมีเลขโดดฐานสิบ ความเที่ยงสิบหลัก การแทนจำนวนจะได้ 1528535047 เป็นซิกนิฟิแคนด์ และเลขชี้กำลังเป็น 5 (โดยจุดฐานถูกสมมติขึ้นที่หลังเลข 1 ซึ่งเป็นเลขโดดที่มีนัยสำคัญมากสุด) และเพื่อที่จะเรียกคืนค่าแท้จริง จะเติมจุดทศนิยมที่หลังเลขโดดตัวแรกของซิกนิฟิแคนด์ แล้วนำไปคูณด้วย แม่แบบ:10^ จนได้ 1.528535047แม่แบบ:E ซึ่งนั่นก็คือจำนวน 152853.5047 ในการเก็บบันทึกจำนวนเช่นนี้ ฐาน 10 ไม่จำเป็นต้องเก็บบันทึกไปด้วย เนื่องจากมันมีใช้เหมือนกันในทุก ๆ จำนวน และสามารถอนุมานได้ในภายหลัง จำนวนนี้จึงอาจเขียนอย่างง่ายได้เป็น 1.528535047 E 5 ซึ่ง "E" กำหนดให้หมายถึง "คูณด้วยสิบยกกำลัง..." เช่นเดียวกับข้อตกลงอันเป็นที่ทราบ
หากเขียนเป็นสัญลักษณ์ ค่าสุดท้ายที่ได้ออกมาคือ
เมื่อ s คือซิกนิฟิแคนด์ที่เติมจุดฐานสมมติเข้าไปแล้ว b คือฐาน และ e คือเลขชี้กำลัง
หรือเทียบเท่ากับประโยคนี้
เมื่อ s คือจำนวนเต็มจากซิกนิฟิแคนด์ทั้งหมดโดยไม่พิจารณาจุดฐานสมมติ ส่วน p คือความเที่ยง (precision) หมายถึงจำนวนหลักของซิกนิฟิแคนด์
ในอดีตที่ผ่านมา ฐานที่แตกต่างกันถูกใช้แทนจำนวนจุดลอยตัว เช่นฐานสองที่เป็นปกติสามัญที่สุด ตามมาด้วยฐานสิบ และฐานสิบหกที่พบได้น้อยกว่า จำนวนจุดลอยตัวถือว่าเป็นจำนวนตรรกยะเพราะมันสามารถเขียนแทนได้ด้วยเศษหนึ่งส่วนจำนวนอื่น อย่างไรก็ตาม ฐานจะเป็นตัวพิจารณาว่าเศษส่วนจะถูกเขียนแทนอย่างไร ตัวอย่างเช่น แม่แบบ:เศษ ไม่สามารถเขียนแทนด้วยจำนวนจุดลอยตัวในฐานสองได้อย่างแม่นยำ แต่สามารถเขียนแทนในฐานสิบได้อย่างถูกต้อง
วิธีการที่ซิกนิฟิแคนด์ เลขชี้กำลัง และบิตเครื่องหมายถูกเก็บบันทึกภายในคอมพิวเตอร์ขึ้นอยู่กับวิธีการทำให้เกิดผล รูปแบบปกติของ IEEE ได้อธิบายรายละเอียดในเวลาต่อมา ตัวอย่างเช่น การแทนจำนวนจุดลอยตัวฐานสองขนาดความเที่ยงหนึ่งเท่า (32 บิต) ซึ่งมีความเที่ยง p = 24 หมายความว่าจะเก็บบันทึกซิกนิฟิแคนด์ได้เป็นสายอักขระ 24 บิต (ประกอบด้วย 0 และ 1) กำหนดให้ค่าของพาย 33 บิตแรกคือ 11001001 00001111 11011010 10100010 0 การปัดเศษให้เหลือ 24 บิตในฐานสองทำได้โดยเพิ่มค่าบิตที่ 24 ซึ่งกระจายมาจากบิตที่ 25 จะได้ 11001001 00001111 11011011 เมื่อเก็บบันทึกในการเข้ารหัส IEEE 754 จำนวนนี้จะกลายเป็นซิกนิฟิแคนด์ s โดยที่ e = 1 (เมื่อสมมติให้จุดทวินิยมอยู่หลังบิตแรกสุดใน s) หลังจากมีการปรับค่าเข้าสู่ทางซ้ายแล้วซึ่งจะทำให้เลขศูนย์นำหน้าหรือตามหลังจำนวนถูกตัดออกถ้ามี (แต่จากตัวอย่างนี้ไม่เกิดผลใด ๆ) ดังนั้นบิตแรกสุดของซิกนิฟิแคนด์จึงเป็น 1 เสมอ (หากค่านั้นไม่ใช่การแทนจำนวน 0) ทำให้เกิดบิตเพิ่มเติมของความเที่ยงซึ่งไม่จำเป็นต้องเก็บบันทึก ค่าของพายจึงคำนวณได้จากสูตร
เมื่อ n คือบิตที่ n จากทางซ้ายของซิกนิฟิแคนด์ที่ปรับแต่งแล้ว การปรับแต่งซิกนิฟิแคนด์หรือเรียกว่า การทำให้เป็นบรรทัดฐาน (normalization) คือการสงวนค่า 1 ที่บวกเข้าไปในภายหลัง และอาจเรียกได้ว่าเป็นรูปแบบหนึ่งของการบีบอัด นั่นคือซิกนิฟิแคนด์ฐานสองจะย่อลงจากเดิมหนึ่งบิตจากความเที่ยงมากสุด ในการประมวลผลเพิ่มเติม
คำว่า แมนทิสซา มักจะใช้เรียกเป็นคำคล้ายกับซิกนิฟิแคนด์แม้ว่ามันจะไม่ถูกต้องนัก เนื่องจากแมนทิสซาในความหมายดั้งเดิมนิยามขึ้นจากส่วนจำนวนเศษของลอการิทึม ในขณะที่ แคแรกเทอริสติก ก็เป็นส่วนจำนวนเต็มของลอการิทึม คำนี้ปรากฏอยู่ในตารางลอการิทึมก่อนที่จะมีคอมพิวเตอร์ใช้กันทั่วไป ตารางลอการิทึมความจริงแล้วก็คือตารางของแมนทิสซา ดังนั้นแมนทิสซาจึงเป็นลอการิทึมของซิกนิฟิแคนด์
การแทนจำนวนที่ไม่ใช่จำนวนเต็มชนิดอื่นในคอมพิวเตอร์
การแทนจำนวนจุดลอยตัว โดยเฉพาะรูปแบบมาตรฐาน IEEE แม้ว่าเป็นวิธีที่ปกติสามัญที่สุดอย่างกว้างขวางสำหรับการแทนจำนวนจริงโดยประมาณในคอมพิวเตอร์ เพราะมันสามารถใช้งานได้ในตัวประมวลผลของคอมพิวเตอร์ขนาดใหญ่ได้อย่างมีประสิทธิภาพ แต่ก็ยังมีทางเลือกอื่น ๆ อีกเช่น
- จำนวนจุดตรึง เป็นการแทนจำนวนที่ใช้การดำเนินการฮาร์ดแวร์จำนวนเต็ม ควบคุมโดยซอฟต์แวร์ที่มีข้อตกลงจำเพาะเกี่ยวกับตำแหน่งของจุดทศนิยมหรือจุดทวินิยม เช่น หกหลักหรือหกบิตจากทางขวา เป็นต้น ฮาร์ดแวร์ที่จัดดำเนินการการแทนจำนวนเช่นนี้ใช้ทรัพยากรน้อยกว่าจำนวนจุดลอยตัว และใช้สำหรับดำเนินการจำนวนเต็ม จำนวนจุดตรึงฐานสองปกติจะใช้ในโปรแกรมประยุกต์ที่มีจุดประสงค์พิเศษ ในตัวประมวลผลฝังตัวที่สามารถคำนวณได้แค่เลขคณิตจำนวนเต็ม แต่จำนวนจุดตรึงฐานสิบจะใช้กับโปรแกรมประยุกต์เชิงพาณิชย์
- เลขฐานสิบเข้ารหัสฐานสอง เป็นการเข้ารหัสเลขฐานสิบซึ่งเลขโดดแต่ละหลักจะถูกแทนด้วยลำดับฐานสองของมันเอง
- หากต้องการความเที่ยงสูงขึ้น เลขคณิตสำหรับจำนวนจุดลอยตัวสามารถสร้างขึ้นได้ (โดยทั่วไปคือในซอฟต์แวร์) ที่มีซิกนิฟิแคนด์แปรความยาวได้ (หรือรวมทั้งเลขชี้กำลังด้วย) ซึ่งจะถูกกำหนดขนาดตามความจำเป็นที่ใช้จริงและตามการดำเนินการคำนวณ สิ่งนี้เรียกว่า เลขคณิตกำหนดความเที่ยงได้ (arbitrary-precision arithmetic)
- จำนวนบางจำนวนไม่สามารถแทนได้อย่างแม่นยำในจำนวนจุดลอยตัวไม่ว่าจะกำหนดความเที่ยงเท่าใด (เช่น แม่แบบ:เศษ และ 0.1) แพกเกจซอฟต์แวร์ที่ดำเนินการเลขคณิตจำนวนตรรกยะ จะแทนที่จำนวนต่าง ๆ เป็นเศษส่วนโดยมีตัวเศษและตัวส่วนเป็นจำนวนเต็ม จึงสามารถให้ผลเป็นจำนวนตรรกยะใด ๆ ได้อย่างถูกต้อง แพกเกจเช่นนั้นจำเป็นต้องใช้เลขคณิตสำหรับจำนวนขนาดใหญ่ (bignum) สำหรับจำนวนเต็มแต่ละจำนวน
- ระบบพีชคณิตคอมพิวเตอร์ อย่างเช่นแมทเทอแมติกาหรือแมกซิมา สามารถจัดการกับจำนวนอตรรกยะอย่างเช่น π หรือ √3 ด้วยวิธีการแบบรูปนัยอย่างสมบูรณ์ โดยไม่ต้องยุ่งกับการเข้ารหัสซิกนิฟิแคนด์ โปรแกรมเหล่านี้จะคำนวณนิพจน์อย่างเช่น sin 3π ได้อย่างแม่นยำ เพราะโปรแกรมทราบถึงคณิตศาสตร์ที่เป็นรากฐาน
- การแทนจำนวนโดยใช้พื้นฐานจากลอการิทึมธรรมชาติบางครั้งพบได้ในโปรแกรมประยุกต์ในเอฟพีจีเอ ที่ซึ่งการดำเนินการเลขคณิตส่วนใหญ่เป็นการคูณและการหาร[2] แนวทางนี้มีความเที่ยงสำหรับจำนวนขนาดเล็กและรองรับช่วงค่ากว้าง เช่นเดียวกับจำนวนจุดลอยตัว
พิสัยของจำนวนจุดลอยตัว
เนื่องจากจุดฐานสามารถเปลี่ยนตำแหน่งได้ สัญกรณ์จำนวนจุดลอยตัวจึงสามารถคำนวณขนาดที่มีพิสัยกว้าง โดยใช้เลขโดดจำนวนหนึ่งตายตัว ในขณะที่ยังคงไว้ซึ่งความเที่ยงที่ดี ตัวอย่างเช่น การคูณที่คำนวณโดยมนุษย์เขียนเป็น
- 0.12 × 0.12 = 0.0144
เมื่อเขียนแทนในระบบจำนวนจุดลอยตัวฐานสิบ ซึ่งมีเลขโดดสามหลัก จะได้
ในขณะที่ระบบจำนวนจุดตรึงที่มีจุดทศนิยมอยู่ทางซ้ายสุด ซึ่งมีเลขโดดสามหลักเช่นกัน จะได้
- 0.120 × 0.120 = 0.014
จะเห็นว่าผลลัพธ์ของจำนวนจุดตรึงสูญหายไปบางส่วน เพราะไม่มีที่อยู่สำหรับเลขโดดที่เกินมา และจุดทศนิยม "ลอยตัว" ไม่ได้ภายในสายอักขระของเลขโดด
พิสัยของจำนวนจุดลอยตัวจึงขึ้นอยู่กับจำนวนบิตหรือเลขโดดที่ใช้สำหรับแทนซิกนิฟิแคนด์ (เลขนัยสำคัญของจำนวน) และเลขชี้กำลัง การแทนจำนวนจุดลอยตัวฐานสองขนาดความเที่ยงสองเท่า (64 บิต) ในระบบคอมพิวเตอร์ทั่วไป จะมีสัมประสิทธิ์ 53 บิต (ซึ่งบิตแรกสุดไม่ต้องเก็บบันทึก) เลขชี้กำลัง 11 บิต และบิตเครื่องหมายอีกหนึ่งบิต จำนวนจุดลอยตัวที่เป็นค่าบวกในรูปแบบนี้จึงมีพิสัยอยู่ที่ประมาณ แม่แบบ:10^ ถึง แม่แบบ:10^ (ค่า 308 มาจาก 1023 × log10 (2) โดยประมาณ และพิสัยของเลขชี้กำลังอยู่ในช่วง [−1022, 1023]) พิสัยโดยรวมทั้งหมดของรูปแบบนี้จึงเก็บบันทึกได้ตั้งแต่ −แม่แบบ:10^ ไปจนถึง +แม่แบบ:10^ (ดูเพิ่มที่ IEEE 754)
จำนวนทั้งหมดของจำนวนจุดลอยตัวที่เป็นบรรทัดฐานแล้วในระบบ F(B, P, L, U) คือ เมื่อ B คือฐานของระบบเลข P คือความเที่ยงของระบบ L คือเลขชี้กำลังน้อยสุดที่สามารถแทนได้ในระบบ และ U คือเลขชี้กำลังมากสุดที่สามารถแทนได้ในระบบ
จำนวนจุดลอยตัวที่เป็นบรรทัดฐานแล้วที่เล็กที่สุดในค่าบวก เรียกว่า ระดับน้อยเกินเก็บ (underflow level) คือ ซึ่งจะมีเลขโดด 1 เป็นตัวนำและ 0 สำหรับหลักที่เหลือทั้งหมดในซิกนิฟิแคนด์ และค่าที่น้อยที่สุดที่เป็นไปได้ของเลขชี้กำลัง
จำนวนจุดลอยตัวที่เป็นบรรทัดฐานแล้วที่ใหญ่ที่สุด เรียกว่า ระดับมากเกินเก็บ (overflow level) คือ ซึ่งจะมีเลขโดด B − 1 สำหรับทุกหลักในซิกนิฟิแคนด์ และค่าที่มากที่สุดที่เป็นไปได้ของเลขชี้กำลัง
นอกจากนี้ก็มีค่าระหว่าง −UFL และ UFL ที่สามารถแทนได้ ซึ่งนั่นก็คือ 0 และ −0 รวมทั้งจำนวนต่ำกว่าบรรทัดฐาน (subnormal number)
ประวัติ

เมื่อ พ.ศ. 2481 คอนรัด ทซูเซอ (Konrad Zuse) จากเบอร์ลิน ประดิษฐ์คอมพิวเตอร์ฐานสองเชิงกลที่สามารถโปรแกรมได้เครื่องแรกชื่อ Z1 ทำงานด้วยจำนวนจุดลอยตัวฐานสอง 22 บิต โดยมีเลขชี้กำลังแบบมีเครื่องหมาย 7 บิต ซิกนิฟิแคนด์ 15 บิต (รวมหนึ่งบิตที่ซ่อนไว้) และบิตเครื่องหมาย 1 บิต หน่วยความจำใช้ส่วนโลหะเลื่อนไปมาเพื่อเก็บบันทึกจำนวนเช่นนั้นได้ 64 จำนวน ต่อมาเครื่อง Z3 ที่พัฒนาด้วยรีเลย์ถูกสร้างขึ้นใน พ.ศ. 2484 ได้พัฒนาเลขคณิตของจำนวนจุดลอยตัวให้เกิดผล ยกเว้นการแทนจำนวนสำหรับค่าอนันต์บวกลบและค่าที่ไม่นิยาม[3]
คอมพิวเตอร์ เชิงพาณิชย์ เครื่องแรกที่มีฮาร์ดแวร์จำนวนจุดลอยตัวคือ Z4 ของทซูเซอ ออกแบบและสร้างขึ้นระหว่าง พ.ศ. 2485–2488 คอมพิวเตอร์มาร์ก V ของเบลล์แลบอลาทอรีส์ใช้งานจำนวนจุดลอยตัวฐานสิบใน พ.ศ. 2489 เวลาต่อมาเกือบทศวรรษคือ พ.ศ. 2497 คอมพิวเตอร์ไอบีเอ็ม 704 ซึ่งใช้หลอดสุญญากาศถูกสร้างขึ้นเพื่อจำหน่ายจำนวนมาก คอมพิวเตอร์รุ่นดังกล่าวได้แนะนำการใช้งานเลขชี้กำลังแบบไบแอส หลายทศวรรษหลังจากนั้น ฮาร์ดแวร์จำนวนจุดลอยตัวเป็นคุณลักษณะทางเลือก และคอมพิวเตอร์ที่มีคุณลักษณะนี้ถูกเรียกว่า "คอมพิวเตอร์วิทยาศาสตร์" หรือมีความสามารถใน "การคำนวณทางวิทยาศาสตร์" ไม่บรรจุเป็นมาตรฐาน จนกระทั่ง พ.ศ. 2532 คอมพิวเตอร์สำหรับ จุดประสงค์ทั่วไป มีความสามารถเกี่ยวกับจำนวนจุดลอยตัวในฮาร์ดแวร์เป็นมาตรฐาน
ชุดคอมพิวเตอร์ยูนิแวก 1100/2200 แนะนำขึ้นเมื่อ พ.ศ. 2505 รองรับรูปแบบจำนวนจุดลอยตัวได้สองรูปแบบ คือความเที่ยงหนึ่งเท่า ซึ่งใช้ 36 บิต แบ่งเป็นบิตเครื่องหมาย 1 บิต เลขชี้กำลัง 8 บิต และซิกนิฟิแคนด์ 27 บิต และความเที่ยงสองเท่า ซึ่งใช้ 72 บิต แบ่งเป็นบิตเครื่องหมาย 1 บิต เลขชี้กำลัง 11 บิต และซิกนิฟิแคนด์ 60 บิต คอมพิวเตอร์ไอบีเอ็ม 7094 แนะนำขึ้นในปีเดียวกัน รองรับทั้งความเที่ยงหนึ่งเท่าและสองเท่า แต่มีรูปแบบที่ต่างไปเล็กน้อย
ก่อนที่จะมีมาตรฐาน IEEE 754 คอมพิวเตอร์ต่าง ๆ ใช้รูปแบบจำนวนจุดลอยตัวในรูปแบบที่ต่างกันมากมาย ซึ่งต่างกันที่ขนาดของเวิร์ด รูปแบบของการแทน และพฤติกรรมการปัดเศษของการดำเนินการ ระบบต่าง ๆ ที่แตกต่างกันนี้ทำให้เกิดการพัฒนาเลขคณิตในฮาร์ดแวร์และซอฟต์แวร์แตกต่างกัน ด้วยความเที่ยงตรงแม่นยำที่ไม่เหมือนกัน
มาตรฐาน IEEE 754 สร้างขึ้นเมื่อ พ.ศ. 2528 หลังจากขนาดของเวิร์ด 32 บิต (หรือ 16 หรือ 64) ได้รับการยอมรับโดยทั่วไป ซึ่งมีพื้นฐานมาจากข้อเสนอของอินเทล ผู้พัฒนาตัวประมวลผลร่วมเชิงตัวเลข อินเทล 8087 ในขณะนั้น[4] นวัตกรรมที่เกิดขึ้นใหม่คือสิ่งเหล่านี้
- การเข้ารหัสบิตต่าง ๆ ระบุไว้อย่างชัดเจน ดังนั้นคอมพิวเตอร์ทุกเครื่องที่ยอมรับจะสามารถแปลผลรูปแบบบิตไปในทางเดียวกัน สิ่งนี้ทำให้สามารถส่งผ่านจำนวนจุดลอยตัวกับคอมพิวเตอร์เครื่องอื่นได้
- พฤติกรรมของการดำเนินการเลขคณิตระบุไว้อย่างชัดเจน สิ่งนี้ทำให้โปรแกรมและค่าที่กำหนด สร้างผลลัพธ์ได้เหมือนกันในคอมพิวเตอร์เครื่องใด ๆ ที่ยอมรับ และช่วยลดความเชื่อว่า การคำนวณจำนวนจุดลอยตัวมีไว้สำหรับพฤติกรรมที่ประหนึ่งว่ากำหนดพิจารณาไม่ได้
- ความสามารถของเงื่อนไขพิเศษ (เช่นภาวะมากเกินเก็บ การหารด้วยศูนย์ ฯลฯ) เพื่อแจ้งผ่านการคำนวณที่ละเอียดอ่อน และจัดการควบคุมได้โดยซอฟต์แวร์
IEEE 754: จำนวนจุดลอยตัวในคอมพิวเตอร์สมัยใหม่
แม่แบบ:บทความหลัก สถาบันวิชาชีพวิศวกรไฟฟ้าและอิเล็กทรอนิกส์ (IEEE) ได้กำหนดมาตรฐานสำหรับการแทนจำนวนจุดลอยตัวฐานสองใน IEEE 754 คอมพิวเตอร์สมัยใหม่เกือบทั้งหมดทำตามมาตรฐานนี้ ข้อยกเว้นที่โดดเด่นคือคอมพิวเตอร์เมนเฟรมของไอบีเอ็ม ซึ่งใช้รูปแบบของมันเอง (สถาปัตยกรรมจุดลอยตัวของไอบีเอ็ม เพิ่มเติมจากรูปแบบฐานสองและฐานสิบจาก IEEE 754) และคอมพิวเตอร์เครย์ ซึ่งรุ่น T90 ใช้ตามรูปแบบของ IEEE แต่รุ่น SV1 ยังคงใช้รูปแบบของมันเอง
มาตรฐานนี้กำหนดรูปแบบหลายชนิดที่เกี่ยวข้องอย่างใกล้ชิด ต่างกันที่รายละเอียดเพียงเล็กน้อย มีห้ารูปแบบเรียกว่า รูปแบบพื้นฐาน และมีอีกสองรูปแบบเป็นรูปแบบที่ใช้อย่างกว้างขวางในฮาร์ดแวร์คอมพิวเตอร์และภาษาโปรแกรมโดยเฉพาะได้แก่
- ความเที่ยงหนึ่งเท่า (single precision) ในตระกูลภาษาซีเรียกว่า "float" และในภาษาฟอร์แทรนเรียกว่า "real" หรือ "real*4" รูปแบบนี้เป็นฐานสองใช้เนื้อที่ 32 บิต (4 ไบต์) และซิกนิฟิแคนด์มีความเที่ยงขนาด 24 บิต (เลขโดดฐานสิบประมาณ 7 หลัก)
- ความเที่ยงสองเท่า (double precision) ในตระกูลภาษาซีเรียกว่า "double" และในภาษาฟอร์แทรนเรียกว่า "double precision" หรือ "real*8" รูปแบบนี้เป็นฐานสองใช้เนื้อที่ 64 บิต (8 ไบต์) และซิกนิฟิแคนด์มีความเที่ยงขนาด 53 บิต (เลขโดดฐานสิบประมาณ 16 หลัก)
รูปแบบพื้นฐานอื่นเช่น ความเที่ยงสี่เท่า (quadruple precision) ฐานสอง (128 บิต) จำนวนจุดลอยตัวฐานสิบ (64 บิต) และจำนวนจุดลอยตัวฐานสิบความเที่ยงสองเท่า (128 บิต) เป็นต้น
รูปแบบที่พบได้น้อยกว่าปกติเช่น
- รูปแบบความเที่ยงแบบขยาย เก็บค่าจำนวนจุดลอยตัว 80 บิต บางครั้งเรียกว่า "long double" ในตระกูลภาษาซี แม้คำว่า "long double" อาจมีความหมายเหมือนกับ "double" หรือใช้แทนความหมายของความเที่ยงสี่เท่า
- ความเที่ยงครึ่งเท่า เก็บค่าจำนวนจุดลอยตัว 16 บิต
จำนวนเต็มใด ๆ ที่มีค่าสัมบูรณ์น้อยกว่าหรือเท่ากับ 224 สามารถแทนในรูปแบบความเที่ยงหนึ่งเท่า และน้อยกว่าหรือเท่ากับ 253 สามารถแทนในรูปแบบความเที่ยงสองเท่า ยิ่งไปกว่านั้น พิสัยอย่างกว้างของกำลังของสอง คูณด้วยจำนวนเช่นนั้นก็สามารถแทนค่าได้ สมบัติเหล่านี้บางครั้งใช้กับข้อมูลจำนวนเต็มเพียงอย่างเดียว เพื่อให้ได้ผลลัพธ์เป็นจำนวนเต็ม 53 บิต บนแพลตฟอร์มที่มีระบบจำนวนจุดลอยตัวความเที่ยงสองเท่า แต่มีระบบจำนวนเต็มเพียง 32 บิต เป็นตัวอย่าง
มาตรฐานนี้ระบุค่าพิเศษบางค่าไว้ด้วยพร้อมทั้งการแทนจำนวน ได้แก่ อนันต์บวก (+∞) อนันต์ลบ (−∞) ลบศูนย์ (−0) ซึ่งต่างจากศูนย์ธรรมดา และค่าไม่ใช่จำนวน (แม่แบบ:Langx)
การเปรียบเทียบจำนวนจุดลอยตัวก็ได้กำหนดไว้ในมาตรฐาน IEEE ซึ่งต่างจากการเปรียบเทียบจำนวนเต็มตามปกติเล็กน้อย นั่นคือลบศูนย์กับบวกศูนย์ถือว่าเท่ากัน และ NaN ไม่เท่ากับจำนวนใด ๆ เลยรวมทั้งตัวมันเองด้วย นอกเหนือจากกรณีพิเศษเหล่านี้ บิตที่มีนัยสำคัญมากกว่าจะถูกเก็บบันทึกก่อนบิตที่มีนัยสำคัญน้อยกว่า ค่าทุกค่ายกเว้น NaN ถือว่าน้อยกว่า +∞ และมากกว่า −∞ อย่างเคร่งครัด
การแทนค่าบิตของจำนวนจุดลอยตัวฐานสองจะแปรตามลอการิทึมฐานสองเพื่อการประมาณค่าอย่างหยาบ ด้วยความคลาดเคลื่อนเฉลี่ยประมาณ 3% (เพราะว่าเขตข้อมูลเลขชี้กำลังอยู่ในส่วนที่มีนัยสำคัญมากกว่าของข้อมูล) สิ่งนี้สามารถใช้ประโยชน์ได้ในโปรแกรมประยุกต์บางโปรแกรม เช่นการปรับความดังในการประมวลผลเสียงดิจิทัล
แม้ว่ารูปแบบ 32 บิต (หนึ่งเท่า) และ 64 บิต (สองเท่า) เป็นรูปแบบสามัญที่สุดในวงกว้าง มาตรฐานนี้ก็อนุญาตให้ใช้ระดับความเที่ยงที่ต่างกันหลายระดับ ฮาร์ดแวร์คอมพิวเตอร์ (อาทิชุดคอมพิวเตอร์อินเทล เพนเทียม และชุดคอมพิวเตอร์โมโตโรลา 68000) มักจะเตรียมรูปแบบความเที่ยงแบบขยาย 80 บิตไว้ให้ โดยมีเลขชี้กำลัง 15 บิต ซิกนิฟิแคนด์ 64 บิต และไม่มีบิตที่ซ่อนไว้
มีการโต้เถียงเกี่ยวกับความล้มเหลวของภาษาโปรแกรมส่วนใหญ่ ที่ไม่สามารถทำรูปแบบความเที่ยงแบบขยายให้โปรแกรมเมอร์ใช้ (ถึงแม้ภาษาซีและภาษาที่เกี่ยวข้อง มักจะเตรียมรูปแบบเหล่านี้ด้วยชนิดข้อมูล long double บนฮาร์ดแวร์เช่นนั้น) ผู้จำหน่ายระบบอาจเตรียมรูปแบบขยายเพิ่มเติม (เช่น 128 บิต) แล้วจำลองการทำงานในซอฟต์แวร์
โครงการปรับปรุงแก้ไขมาตรฐาน IEEE 754 เริ่มขึ้นในปี พ.ศ. 2543 แล้วเสร็จและอนุมัติในเดือนมิถุนายน พ.ศ. 2551 มาตรฐานนี้มีรูปแบบจำนวนจุดลอยตัวฐานสิบหลายแบบ และจำนวนจุดลอยตัวฐานสอง 16 บิตหนึ่งแบบ (binary16) จำนวนจุดลอยตัวฐานสอง 16 บิตมีโครงสร้างและกฎเหมือนรูปแบบของเดิม มีใช้ในภาษาซีจีของเอ็นวิเดียและมาตรฐาน openEXR[5]
การแทนค่าภายใน
โดยทั่วไปจำนวนจุดลอยตัวบรรจุอยู่ในข้อมูลคอมพิวเตอร์ เป็นบิตเครื่องหมาย เขตข้อมูลเลขชี้กำลัง และเขตข้อมูลซิกนิฟิแคนด์ (แมนทิสซา) ตามลำดับจากซ้ายไปขวา สำหรับรูปแบบ IEEE 754 ในฐานสองจะถูกแบ่งสรรดังนี้
| ชนิด | เครื่องหมาย | เลขชี้กำลัง | ซิกนิฟิแคนด์ | บิตทั้งหมด | ไบแอสของเลขชี้กำลัง | ความเที่ยงของบิต | |
|---|---|---|---|---|---|---|---|
| ความเที่ยงครึ่งเท่า | 1 | 5 | 10 | 16 | 15 | 11 | |
| ความเที่ยงหนึ่งเท่า | 1 | 8 | 23 | 32 | 127 | 24 | |
| ความเที่ยงสองเท่า | 1 | 11 | 52 | 64 | 1023 | 53 | |
| ความเที่ยงสี่เท่า | 1 | 15 | 112 | 128 | 16383 | 113 |
เมื่อเลขชี้กำลังเป็นบวกหรือลบ จะเก็บบันทึกเป็นจำนวนไม่มีเครื่องหมายซึ่งบวกไบแอส (bias) แบบคงที่เข้าไป (เช่นค่า −9 บวกด้วยไบแอส 15 จะเก็บเป็นค่า 6) เมื่อเลขชี้กำลังเป็น 0 ทุกบิต จะสงวนไว้สำหรับค่าศูนย์และจำนวนต่ำกว่าบรรทัดฐาน และเมื่อเลขชี้กำลังเป็น 1 ทุกบิต จะสงวนไว้สำหรับค่าอนันต์และ NaN พิสัยของเลขชี้กำลังของจำนวนบรรทัดฐานคือ [−126, 127] สำหรับความเที่ยงหนึ่งเท่า [−1022, 1023] สำหรับความเที่ยงสองเท่า ฯลฯ จำนวนบรรทัดฐานไม่รวมค่าทั้งสี่ประเภทได้แก่ ศูนย์ จำนวนต่ำกว่าบรรทัดฐาน อนันต์ และ NaN
ในรูปแบบเพื่อการแลกเปลี่ยนข้อมูลฐานสองของ IEEE บิตแรกสุดของซิกนิฟิแคนด์ที่ทำให้เป็นบรรทัดฐานแล้วซึ่งเป็น 1 ความจริงแล้วจะไม่ถูกเก็บบันทึกในข้อมูลคอมพิวเตอร์ บิตนี้เรียกว่า "บิตที่ซ่อน" หรือ "บิตโดยนัย" ด้วยเหตุนี้ความเที่ยงจึงเพิ่มขึ้น 1 บิตจากซิกนิฟิแคนด์ที่เก็บบันทึก รูปแบบความเที่ยงหนึ่งเท่าจึงมีความเที่ยงแท้จริง 24 บิต รูปแบบความเที่ยงสองเท่ามี 53 บิต ฯลฯ
ตัวอย่างเช่น จำนวนต่อไปนี้คือค่า π ในฐานสอง ปัดเศษที่ความเที่ยง 24 บิต จะได้
- เครื่องหมาย = 0 ; e = 1 ; s = 110010010000111111011011 (บิตแรกสุดคือบิตที่ซ่อน)
ในรูปแบบความเที่ยงหนึ่งเท่า ผลบวกระหว่างเลขชี้กำลัง 1 กับไบแอส 127 คือ 128 (10000000) ดังนั้นจะแทนค่าได้เป็น
- 0 10000000 10010010000111111011011 (ตัดบิตที่ซ่อนออก) = 40490FDB ในเลขฐานสิบหก[6]
จำนวนพิเศษ
ศูนย์มีเครื่องหมาย
แม่แบบ:บทความหลัก ในมาตรฐาน IEEE 754 ค่าศูนย์มีเครื่องหมาย หมายความว่ามีทั้ง "บวกศูนย์" (+0) และ "ลบศูนย์" (−0) ในสภาวะแวดล้อมขณะทำงานส่วนใหญ่ ค่าบวกศูนย์โดยทั่วไปพิมพ์เป็น "0" และค่าลบศูนย์อาจพิมพ์เป็น "-0" จำนวนทั้งสองมีความเท่ากันในการเปรียบเทียบเชิงจำนวน แต่การดำเนินการบางอย่างกับ +0 และ −0 จะให้ผลลัพธ์ที่ต่างออกไป ตัวอย่างเช่น 1 / (−0) จะให้ผลเป็นค่าอนันต์ที่เป็นลบ ในขณะที่ 1 / (+0) จะให้ผลเป็นค่าอนันต์ที่เป็นบวก อย่างไรก็ตามการดำเนินการดังกล่าวจะเกิดขึ้นพร้อมกับสิ่งผิดปรกติ "การหารด้วยศูนย์" หรืออีกตัวอย่างหนึ่ง การดำเนินการ arccot สมมาตรมีเครื่องหมาย จะให้ผลลัพธ์ต่างกับสำหรับ +0 และ −0 โดยไม่มีสิ่งผิดปรกติ ความแตกต่างระหว่าง +0 และ −0 เป็นที่สังเกตได้มากที่สุดในการดำเนินการเชิงซ้อนที่ส่วนตัดแบรนช์ (branch cut)
จำนวนต่ำกว่าบรรทัดฐาน
แม่แบบ:บทความหลัก จำนวนต่ำกว่าบรรทัดฐาน (subnormal number) เป็นจำนวนที่เติมในช่องว่างน้อยเกินเก็บ (underflow gap) ด้วยค่าซึ่งระยะห่างสัมบูรณ์ระหว่างจำนวนต่ำกว่าบรรทัดฐาน เหมือนกับจำนวนอื่นที่อยู่ติดกันนอกช่องว่างน้อยเกินเก็บนี้ สิ่งนี้เป็นการปรับปรุงการปฏิบัติแบบเก่าซึ่งให้ค่าเป็นศูนย์เท่านั้นภายในช่องว่างน้อยเกินเก็บ และผลลัพธ์ที่น้อยเกินเก็บถูกแทนที่ด้วยศูนย์ (ถูกปัดเศษทิ้งเป็นศูนย์)
ฮาร์ดแวร์จำนวนจุดลอยตัวสมัยใหม่สามารถจัดการจำนวนต่ำกว่าบรรทัดฐานเหล่านี้ได้ เช่นเดียวกับจำนวนบรรทัดฐาน และไม่ต้องการการจำลองจากซอฟต์แวร์
อนันต์
- รายละเอียดเพิ่มเติมเกี่ยวกับแนวคิดของอนันต์ ดูที่ อนันต์
อนันต์บนเส้นจำนวนจริงขยายสามารถแทนได้ในชนิดข้อมูลจำนวนจุดลอยตัว IEEE เช่นเดียวกับจำนวนจุดลอยตัวทั่วไปอย่าง 1 หรือ 1.5 ค่านี้ไม่ใช่ค่าที่เกิดความผิดพลาด ถึงแม้ว่ามันจะใช้แทนค่าที่มากเกินเก็บ (overflow) (แต่ไม่เสมอไป ขึ้นอยู่กับการปัดเศษ) เมื่อเกิดสิ่งผิดปรกติของการหารด้วยศูนย์ จะคืนค่าอนันต์ที่เป็นบวกหรือลบออกมาเป็นผลลัพธ์ ค่าอนันต์สามารถแนะนำให้เป็นจำนวนจำนวนหนึ่ง (เหมือนแมโคร INFINITY ของภาษาซี หรือ ∞ ถ้าภาษาโปรแกรมนั้นอนุญาตให้ใช้ได้)
IEEE 754 ต้องการการจัดการอนันต์อย่างสมเหตุสมผล ตัวอย่างเช่น
- (+∞) + (+7) = (+∞)
- (+∞) × (−2) = (−∞)
- (+∞) × 0 = NaN (ไม่มีความหมาย)
ค่าไม่ใช่จำนวน
แม่แบบ:บทความหลัก IEEE 754 ระบุค่าพิเศษอีกอย่างหนึ่งคือค่าไม่ใช่จำนวน (แม่แบบ:Langx) เพื่อคืนค่าเป็นผลลัพธ์สำหรับการดำเนินการที่ "ไม่สมเหตุสมผล" ตัวอย่างเช่น 0/0, ∞×0, sqrt(−1) เป็นต้น NaN แท้จริงแล้วมีสองชนิดคือ signaling และ quiet การใช้ signaling NaN ในการดำเนินการเลขคณิตใด ๆ (รวมทั้งการเปรียบเทียบเชิงจำนวน) ทำให้เกิดสิ่งผิดปรกติ "ไม่สมเหตุสมผล" ส่วนการใช้ quiet NaN จะได้ผลลัพธ์เป็น NaN เท่านั้นโดยไม่เกิดสิ่งผิดปรกติ
การแทนค่า NaN ที่กำหนดโดยมาตรฐาน มีบางบิตที่ไม่ระบุซึ่งอาจใช้เข้ารหัสชนิดของข้อผิดพลาดได้ แต่ก็ไม่มีมาตรฐานสำหรับการเข้ารหัสนี้ ในทางทฤษฎี signaling NaN สามารถใช้กับระบบขณะทำงาน (runtime system) เพื่อขยายจำนวนจุดลอยตัวด้วยค่าพิเศษอื่น โดยไม่ต้องชะลอการคำนวณกับจำนวนธรรมดา แม้ว่าการขยายเช่นนั้นดูเหมือนว่าไม่เป็นสิ่งปกติสามัญ
จำนวนที่แทนได้ การแปลง และการปัดเศษ
โดยธรรมชาติแล้ว จำนวนทุกจำนวนที่สามารถเขียนให้อยู่ในรูปแบบจำนวนจุดลอยตัว เป็นจำนวนตรรกยะที่มีจุดฐานรู้จบในฐานที่สัมพันธ์กัน (เช่นทศนิยมรู้จบในฐานสิบ หรือทวินิยมรู้จบในฐานสอง) ส่วนจำนวนอตรรกยะอย่างเช่น π หรือ √2 หรือจำนวนตรรกยะที่มีจุดฐานไม่รู้จบต้องใช้เป็นค่าประมาณ จำนวนของเลขโดด (หรือบิต) ของความเที่ยงก็เป็นตัวจำกัดเซตของจำนวนตรรกยะที่สามารถแทนค่าได้อย่างแม่นยำ ตัวอย่างเช่น จำนวน 123456789 จะไม่สามารถแทนค่าได้อย่างแม่นยำถ้ามีความเที่ยงบนเลขโดดฐานสิบเพียงแปดหลัก เป็นต้น
เมื่อจำนวนหนึ่งถูกแทนค่าในรูปแบบอย่างหนึ่ง (เช่นสายอักขระ) ซึ่งไม่ใช่การแทนจำนวนจุดลอยตัวพื้นเดิมที่รองรับในคอมพิวเตอร์ จำนวนนั้นจะต้องถูกแปลงก่อนนำมาใช้ในระบบคอมพิวเตอร์ ถ้าหากจำนวนนั้นสามารถแทนค่าในรูปแบบจำนวนจุดลอยตัวได้อย่างแม่นยำ การแปลงนั้นก็จะถูกต้องแม่นยำด้วย ถ้าหากไม่สามารถแทนค่าได้อย่างแม่นยำ การแปลงก็จะต้องเลือกจำนวนจุดลอยตัวอื่นมาใช้แทนค่าดั้งเดิม ซึ่งค่าที่ถูกเลือกนี้มีค่าต่างจากค่าดั้งเดิม และค่าที่ถูกปรับแต่งเรียกว่า ค่าจากการปัดเศษ
จำนวนตรรกยะไม่จำเป็นว่าต้องมีจุดฐานรู้จบในฐานที่สัมพันธ์กัน ตัวอย่างเช่น จำนวน แม่แบบ:เศษ ในฐานสิบเป็นทศนิยมรู้จบ (0.5) ในขณะที่ แม่แบบ:เศษ เป็นทศนิยมไม่รู้จบ (0.333…) จำนวนตรรกยะในฐานสองที่มีตัวส่วนเป็นกำลังของ 2 เท่านั้นที่เป็นทวินิยมรู้จบ (เช่น แม่แบบ:เศษ หรือ แม่แบบ:เศษ) จำนวนตรรกยะที่มีตัวส่วนเป็นตัวประกอบเฉพาะอื่นนอกจาก 2 เป็นทวินิยมไม่รู้จบ สิ่งนี้หมายความว่า จำนวนที่สั้นและแม่นยำซึ่งเขียนในฐานสิบ อาจจำเป็นต้องประมาณค่าเมื่อแปลงเป็นจำนวนจุดลอยตัวฐานสอง เช่น จำนวนฐานสิบ 0.1 ไม่สามารถแทนค่าได้อย่างแม่นยำในจำนวนจุดลอยตัวฐานสองอันมีความเที่ยงจำกัด การแทนฐานสองจะได้ลำดับ "1100" ซ้ำไปเรื่อย ๆ ไม่รู้จบ
- e = −4; s = 1100110011001100110011001100110011…
เมื่อ s คือซิกนิฟิแคนด์และ e คือเลขชี้กำลัง ดังที่เคยอธิบายไว้ก่อนหน้า
เมื่อปัดเศษให้เหลือ 24 บิตจะกลายเป็น
- e = −4; s = 110011001100110011001101
ซึ่งมีค่าที่แท้จริงเท่ากับ 0.100000001490116119384765625 ในฐานสิบ
หรืออีกตัวอย่างหนึ่ง จำนวนจริง π เขียนแทนในฐานสองด้วยลำดับบิตไม่รู้จบได้เป็น
- 11.0010010000111111011010101000100010000101101000110000100011010011…
เมื่อปัดเศษให้เหลือ 24 บิตจะกลายเป็น
- 11.0010010000111111011011
ในจำนวนจุดลอยตัวฐานสองแบบความเที่ยงหนึ่งเท่า จำนวนนี้จะแทนค่าด้วย s = 1.10010010000111111011011 และ e = 1 ซึ่งจำนวนนี้มีค่าในฐานสิบเป็น
- 3.1415927410125732421875
ในขณะที่การประมาณค่า π ที่เที่ยงตรงมากกว่าควรจะเป็น
- 3.1415926535897932384626433832795…
ผลลัพธ์ของการปัดเศษต่างจากค่าที่แท้จริงประมาณ 0.03 ส่วนต่อล้านส่วน และตรงกับเลขฐานสิบของ π เพียง 7 หลักแรก ส่วนต่างนี้เรียกว่าค่าคลาดเคลื่อนของความไม่ต่อเนื่อง (discretization error) และถูกจำกัดโดยเอปไซลอนเครื่องจักร (machine epsilon)
ผลต่างเชิงเลขคณิตระหว่างจำนวนจุดลอยตัวสองจำนวนที่สามารถแทนค่าได้และอยู่ติดกันตามลำดับ ซึ่งมีเลขชี้กำลังเดียวกัน ผลต่างนี้เรียกว่า หน่วยในตำแหน่งสุดท้าย (unit in the last place: ULP) ตัวอย่างเช่น ถ้าหากไม่มีจำนวนที่แทนค่าได้อยู่ระหว่าง 1.45a70c2216 กับ 1.45a70c2416 หน่วยในตำแหน่งสุดท้ายก็คือ 2×16−8 หรือเท่ากับ 2−31 สำหรับจำนวนที่มีเลขชี้กำลังเป็น 0 หน่วยในตำแหน่งสุดท้ายจะเท่ากับ 2−23 หรือประมาณ 10−7 ในความเที่ยงหนึ่งเท่า และประมาณ 10−16 ในความเที่ยงสองเท่า พฤติกรรมที่ถูกกำหนดของฮาร์ดแวร์ที่ยอมรับมาตรฐาน IEEE คือผลลัพธ์ต้องอยู่ภายในครึ่งหนึ่งของหน่วยในตำแหน่งสุดท้าย
วิธีการปัดเศษ
การปัดเศษจะถูกใช้เมื่อผลลัพธ์ที่ถูกต้องที่ได้จากการดำเนินการจำนวนจุดลอยตัว (หรือการแปลงเป็นรูปแบบจุดลอยตัว) มีเลขโดดมากเกินกว่าที่จะเก็บได้ในซิกนิฟิแคนด์ การปัดเศษมีวิธีการหลายแบบที่ต่างกัน แนวทางทั่วไปในอดีตคือการปัดเศษทิ้ง (truncation) และตั้งแต่มีการแนะนำ IEEE 754 แบบวิธีเริ่มต้นคือการปัดเศษเลขคู่ใกล้สุด หรือเรียกว่าการปัดเศษของนักธนาคาร (Banker's Rounding) มีใช้อย่างปกติสามัญมากกว่า แบบวิธีนี้จะปัดเศษผลลัพธ์ในอุดมคติ (ที่มีความเที่ยงอนันต์) จากการดำเนินการเลขคณิต ไปสู่จำนวนที่สามารถแทนค่าได้ที่ใกล้ที่สุด และให้ผลเป็นการแทนค่านั้นออกมา[note 1] ในกรณีที่ผลลัพธ์อยู่กึ่งกลาง ค่าที่มีซิกนิฟิแคนด์ลงท้ายเป็นเลขคู่จะถูกเลือก มาตรฐาน IEEE 754 กำหนดว่าจำเป็นต้องใช้วิธีการปัดเศษเดียวกันในทุก ๆ การดำเนินการพีชคณิตพื้นฐาน ซึ่งรวมถึงรากที่สองและการแปลงจำนวน เมื่อผลลัพธ์เป็นค่าเชิงตัวเลข สิ่งนี้หมายความว่า ผลลัพธ์จากการดำเนินการ IEEE 754 จะถูกพิจารณาทุกบิตในผลลัพธ์ ยกเว้นค่า NaN (ฟังก์ชัน "ไลบรารี" อาทิโคไซน์หรือลอการิทึมไม่ถูกบังคับ)
วิธีการปัดเศษทางเลือกอื่นก็มีให้ใช้ได้ IEEE 754 ได้ระบุวิธีการปัดเศษไว้ดังนี้
- ปัดเศษสู่ค่าใกล้สุด ซึ่งค่าที่อยู่กึ่งกลางจะปัดเศษสู่เลขโดดที่เป็นเลขคู่ที่อยู่ใกล้สุดในตำแหน่งที่ต้องการ (วิธีการปริยายและปกติสามัญที่สุด)
- ปัดเศษสู่ค่าใกล้สุด ซึ่งค่าที่อยู่กึ่งกลางจะปัดเศษในทิศทางออกจากศูนย์ (เป็นทางเลือกสำหรับจำนวนจุดลอยตัวฐานสอง และเป็นปกติสามัญในฐานสิบ)
- ปัดเศษขึ้น (ในทิศทางเข้าสู่ +∞ ดังนั้นค่าลบจะปัดเศษเข้าหาศูนย์)
- ปัดเศษลง (ในทิศทางเข้าสู่ −∞ ดังนั้นค่าลบจะปัดเศษออกจากศูนย์)
- ปัดเศษเข้าหาศูนย์ (การปัดเศษทิ้ง คล้ายพฤติกรรมปกติในการแปลงจำนวนจุดลอยตัวเป็นจำนวนเต็ม เช่นจาก −3.9 เป็น −3)
แบบวิธีทางเลือกต่าง ๆ มีประโยชน์เมื่อจำนวนของค่าคลาดเคลื่อนต้องถูกจำกัดขอบเขต การประยุกต์ที่จำเป็นต้องใช้ค่าคลาดเคลื่อนที่จำกัดขอบเขต คือจำนวนจุดลอยตัวหลายความเที่ยง และเลขคณิตอันตรภาค (interval aritmetics)
การใช้งานการปัดเศษเพิ่มเติมคือ การปัดเศษจำนวนให้มีจำนวนหลักที่ต้องการในฐานสิบ (หรือฐานสอง) เช่นในการปัดเศษผลลัพธ์สกุลเงิน (จุดทศนิยมสองหลัก)
การดำเนินการเลขคณิตจุดลอยตัว
เพื่อความง่ายในการนำเสนอและการทำความเข้าใจ ตัวอย่างต่อไปนี้จะใช้เลขฐานสิบที่มีความเที่ยง 7 หลัก ตามที่ระบุไว้ใน IEEE 754 รูปแบบฐานสิบ 32 บิต หลักการพื้นฐานนั้นเหมือนกันในฐานหรือความเที่ยงใด ๆ เว้นแต่การทำให้เป็นบรรทัดฐานเป็นทางเลือกที่ไม่บังคับ (มันไม่ส่งผลต่อค่าเชิงจำนวนของผลลัพธ์) s ในที่นี้หมายถึงซิกนิฟิแคนด์และ e คือเลขชี้กำลัง
การบวกและการลบ
วิธีการอย่างง่ายในการบวกจำนวนจุดลอยตัวคือ อันดับแรกต้องทำเลขชี้กำลังให้เหมือนกันเสียก่อน จากตัวอย่างต่อไปนี้ จำนวนที่สองถูกเลื่อนจุดฐานไปทางขวาสามหลัก จากนั้นจึงกระทำการบวกธรรมดา
123456.7 = 1.234567 × 10^5 101.7654 = 1.017654 × 10^2 = 0.001017654 × 10^5
ดังนั้น
123456.7 + 101.7654 = (1.234567 × 10^5) + (1.017654 × 10^2)
= (1.234567 × 10^5) + (0.001017654 × 10^5)
= (1.234567 + 0.001017654) × 10^5
= 1.235584654 × 10^5
โดยรายละเอียด
e=5; s=1.234567 (123456.7) + e=2; s=1.017654 (101.7654)
e=5; s=1.234567 + e=5; s=0.001017654 (หลังจากเลื่อนจุดฐานแล้ว) -------------------- e=5; s=1.235584654 (ผลบวกแท้จริง 123558.4654)
ผลบวกนี้เป็นค่าแท้จริงที่ถูกต้องแม่นยำ มันจะถูกปัดเศษให้เหลือเพียงเจ็ดหลัก แล้วทำให้เป็นบรรทัดฐานหากจำเป็น ดังนั้นผลลัพธ์สุดท้ายคือ
e=5; s=1.235585 (ผลลัพธ์สุดท้าย 123558.5)
สังเกตว่าสามหลักสุดท้ายจากการบวก (654) สูญเสียไปอย่างสำคัญ สิ่งนี้เรียกว่าค่าคาดเคลื่อนการปัดเศษ (round-off error) ในกรณีสุดขีด ผลบวกของจำนวนสองจำนวนที่ไม่เป็นศูนย์อาจเท่ากับค่าเดิมของจำนวนใดจำนวนหนึ่ง
e=5; s=1.234567 + e=-3; s=9.876543
e=5; s=1.234567 + e=5; s=0.00000009876543 (หลังจากเลื่อนจุดฐานแล้ว) ---------------------- e=5; s=1.23456709876543 (ผลบวกแท้จริง) e=5; s=1.234567 (หลังจากปัดเศษ/ทำให้เป็นบรรทัดฐาน)
อีกตัวอย่างหนึ่งของปัญหาการสูญเสียนัยสำคัญ เกิดขึ้นในการลบสองจำนวนที่มีค่าใกล้เคียงกัน จากตัวอย่างนี้ แม่แบบ:Nowrap และ แม่แบบ:Nowrap เป็นการแทนค่าของจำนวนตรรกยะ 123457.1467 และ 123456.659 ตามลำดับ
e=5; s=1.234571 − e=5; s=1.234567 ---------------- e=5; s=0.000004 e=−1; s=4.000000 (หลังจากปัดเศษ/ทำให้เป็นบรรทัดฐาน)
การแทนค่าที่ดีที่สุดของผลต่างนี้ควรเป็น แม่แบบ:Nowrap ซึ่งต่างจากผลลัพธ์ แม่แบบ:Nowrap อยู่มากกว่า 20% ในกรณีสุดขีด ผลลัพธ์สุดท้ายอาจกลายเป็นศูนย์แม้ว่าการคำนวณที่แท้จริงอาจได้ค่าหลายล้าน การสูญเสียนัยสำคัญเช่นนี้แสดงให้เห็นถึงความอันตรายในการสมมติว่า เลขโดดทุกหลักของผลลัพธ์ที่คำนวณได้ล้วนมีความหมาย การรับมือต่อผลสืบเนื่องของค่าคลาดเคลื่อนเหล่านี้เป็นหัวข้อศึกษาอันหนึ่งในการวิเคราะห์เชิงตัวเลข (numerical analysis) ดูเพิ่มที่ ปัญหาความแม่นยำ
การคูณและการหาร
การคูณกระทำได้โดยคูณซิกนิฟิแคนด์ทั้งสอง และบวกเลขชี้กำลังเข้าด้วยกัน ผลลัพธ์ที่ได้จะถูกปัดเศษและทำให้เป็นบรรทัดฐาน
e=3; s=4.734612 × e=5; s=5.417242 ----------------------- e=8; s=25.648538980104 (ผลคูณแท้จริง) e=8; s=25.64854 (หลังจากปัดเศษ) e=9; s=2.564854 (หลังจากทำให้เป็นบรรทัดฐาน)
การหารก็กระทำด้วยวิธีที่คล้ายกันนี้ แต่ซับซ้อนมากกว่า
การคูณและการหารไม่เกิดปัญหาการสูญเสียหรือการดูดกลืนนัยสำคัญ แม้ว่าค่าคลาดเคลื่อนจำนวนน้อยอาจถูกสะสมในการดำเนินการที่กระทำซ้ำ ๆ[7] ในทางปฏิบัติ แนวทางของการดำเนินการเหล่านี้ค่อนข้างซับซ้อนในตรรกะดิจิทัล ดูที่ขั้นตอนวิธีการคูณของบูทและการหารเชิงดิจิทัล[note 2] สำหรับวิธีการที่รวดเร็วและง่าย ดูที่แบบแผนของฮอร์เนอร์
การรับมือกับกรณีผิดปรกติ
การคำนวณจำนวนจุดลอยตัวในคอมพิวเตอร์สามารถทำให้เกิดปัญหาสามประเภทได้แก่
- การดำเนินการที่ไม่ถูกต้องในทางคณิตศาสตร์ เช่นการหารด้วยศูนย์
- การดำเนินการที่ถูกต้องในหลักการ แต่ไม่รองรับโดยรูปแบบที่กำหนด ตัวอย่างเช่น การคำนวณรากที่สองของ −1 หรืออินเวิร์สไซน์ของ 2 (ทั้งสองให้ผลเป็นจำนวนเชิงซ้อน)
- การดำเนินการที่ถูกต้องในหลักการ แต่ผลลัพธ์ที่ได้ไม่สามารถแทนค่าในรูปแบบที่กำหนดได้เลย เนื่องจากเลขชี้กำลังมีขนาดใหญ่หรือเล็กเกินกว่าที่จะเข้ารหัสลงในเขตข้อมูลเลขชี้กำลัง เหตุการณ์เช่นนี้มีทั้ง ภาวะมากเกินเก็บ (overflow เลขชี้กำลังใหญ่เกินไป) ภาวะน้อยเกินเก็บ (underflow เลขชี้กำลังเลขเกินไป) หรือการทำจำนวนให้ต่ำกว่าบรรทัดฐาน (denormalization สูญเสียความเที่ยง)
ก่อนที่จะมีมาตรฐาน IEEE เงื่อนไขดังกล่าวมักทำให้โปรแกรมหยุดทำงาน หรือกระตุ้นให้เกิดกับดัก (trap) ที่โปรแกรมเมอร์สามารถตรวจจับได้ แนวทางที่สิ่งนี้ทำงานขึ้นอยู่กับระบบ หมายความว่าโปรแกรมที่ใช้จำนวนจุดลอยตัวจะไม่สามารถย้ายไปทำงานบนเครื่องอื่นได้
มาตรฐานต้นฉบับ IEEE 754 (พ.ศ. 2527) เป็นก้าวแรกของวิธีการมาตรฐานสำหรับการดำเนินงานตาม IEEE 754 ในการบันทึกข้อผิดพลาดเกิดขึ้น ต่อไปนี้เราจะไม่พิจารณาการตรวจจับกับดัก (ซึ่งเป็นทางเลือกในรุ่น พ.ศ. 2527) และ "โหมดการจัดการสิ่งผิดปรกติแบบอื่น" (ซึ่งมาแทนที่การตรวจจับกับดักในรุ่น พ.ศ. 2551 แต่ก็ยังคงเป็นทางเลือก) แต่พิจารณาแค่แบบวิธีที่จำเป็นในการจัดการสิ่งผิดปรกติตาม IEEE 754 สิ่งผิดปรกติเชิงเลขคณิตต้องถูกบันทึกลงในบิตแสดงความผิดพลาดแบบ "ยึดติด" โดยปริยาย คำว่า "ยึดติด" หมายความว่า บิตแสดงความผิดพลาดจะไม่ถูกตั้งใหม่โดยการดำเนินการเลขคณิตถัดไป แต่จะยังคงมีค่าอยู่จนกว่าสั่งให้ตั้งใหม่อย่างแน่ชัด โดยปกติแล้วการดำเนินการหนึ่ง ๆ จะให้ผลลัพธ์ตามข้อกำหนดเสมอโดยไม่ยับยั้งการคำนวณ ตัวอย่างเช่น 1/0 ให้ผลลัพธ์เป็น +∞ พร้อมตั้งค่าบิตความผิดพลาดของการหารด้วยศูนย์ด้วย
อย่างไรก็ตามมาตรฐานต้นฉบับ IEEE 754 มิได้แนะนำการดำเนินการต่าง ๆ เพื่อจัดการกับกลุ่มของบิตความผิดพลาดเหล่านั้น ดังนั้นเมื่อสิ่งเหล่านี้ถูกพัฒนาในฮาร์ดแวร์ การทำให้เกิดผลจากภาษาโปรแกรมแต่เริ่มแรกจึงไม่ได้จัดเตรียมมาตรการเพื่อเข้าถึงมัน (นอกจากแอสเซมเบลอร์) ในเวลาต่อมามาตรฐานของภาษาโปรแกรมบางภาษา (เช่นภาษาซีหรือภาษาฟอร์แทรน) ได้ปรับปรุงเพื่อระบุแบบวิธีสำหรับเข้าถึงและเปลี่ยนแปลงสถานภาพกับบิตความผิดพลาด มาตรฐาน IEEE 754 รุ่น พ.ศ. 2551 ที่ใช้อยู่ในปัจจุบันจึงได้ระบุการดำเนินการบางชนิดสำหรับเข้าถึงและจัดการบิตความผิดพลาดเชิงเลขคณิต ตัวแบบการเขียนโปรแกรมที่มีพื้นฐานการทำงานเทร็ดเดียวแต่ถูกใช้โดยหลายเทร็ด จะต้องมีมาตรการเกี่ยวกับภาวะพร้อมกันนอกเหนือไปจากมาตรฐาน
IEEE 754 กำหนดความผิดพลาดเชิงเลขคณิตห้าประการที่ต้องถูกบันทึกในบิตความผิดพลาดที่ "ยึดติด" ดังนี้
- ไม่แม่นยำ (inexact) บิตนี้จะถูกตั้งค่า ถ้าค่าที่ปัดเศษและส่งคืนจากการดำเนินการ ต่างจากผลลัพธ์แท้จริงในทางคณิตศาสตร์
- น้อยเกินเก็บ (underflow) บิตนี้จะถูกตั้งค่า ถ้าค่าที่ปัดเศษมีขนาดเล็ก และ ไม่แม่นยำ ให้ผลเป็นค่าต่ำกว่าบรรทัดฐาน (รวมทั้งศูนย์ด้วย)
- มากเกินเก็บ (overflow) บิตนี้จะถูกตั้งค่า ถ้าค่าสัมบูรณ์ของค่าที่ปัดเศษมีขนาดใหญ่เกินกว่าที่จะแทนได้ ค่าที่ส่งคืนอาจเป็นอนันต์หรือจำนวนมากสุดที่แทนค่าได้ ขึ้นอยู่กับวิธีการปัดเศษ
- หารด้วยศูนย์ (divide-by-zero) บิตนี้จะถูกตั้งค่า ถ้าผลลัพธ์เป็นค่าไม่จำกัดอันเกิดจากตัวดำเนินการจำกัด ให้ค่าเป็น +∞ หรือ −∞ อย่างใดอย่างหนึ่ง
- ไม่สมเหตุสมผล (invalid) บิตนี้จะถูกตั้งค่า ถ้าไม่สามารถคืนค่าผลลัพธ์จำนวนจริงได้อาทิ sqrt(−1) หรือ 0/0 จะคืนค่าเป็น quiet NaN แทน
ปัญหาความแม่นยำ
ข้อเท็จจริงที่ว่าจำนวนจุดลอยตัวไม่สามารถแทนค่าจำนวนจริงทั้งหมดได้อย่างแม่นยำ และการดำเนินการจุดลอยตัวไม่อาจใช้แทนการดำเนินการเลขคณิตที่แท้จริงได้ นำมาซึ่งสถานการณ์ที่ไม่คาดหวัง สิ่งนี้เกี่ยวข้องกับความเที่ยงที่มีขนาดจำกัดที่คอมพิวเตอร์ใช้แทนจำนวนต่าง ๆ
จากตัวอย่างต่อไปนี้ 0.1 และ 0.01 ในฐานสิบไม่สามารถแทนค่าได้ในฐานสองอย่างแม่นยำ หมายความว่าผลลัพธ์ของการพยายามคำนวณ 0.1 ยกกำลังสอง จะไม่ได้จำนวน 0.01 หรือจำนวนที่แทนค่าได้และใกล้เคียงที่สุดเลย ในการแทนค่า 24 บิต (ความเที่ยงหนึ่งเท่า) จำนวน 0.1 ฐานสิบ ดังที่เคยกล่าวไว้ว่าแทนค่าได้เป็น แม่แบบ:Nowrap มีค่าที่แท้จริงเท่ากับ
- 0.100000001490116119384765625
เมื่อนำจำนวนนี้มายกกำลังสองจะได้ผลลัพธ์แท้จริงเป็น
- 0.010000000298023226097399174250313080847263336181640625
หากนำมายกกำลังสองด้วยฮาร์ดแวร์จุดลอยตัวความเที่ยงหนึ่งเท่า (พร้อมทั้งปัดเศษ) จะได้
- 0.010000000707805156707763671875
แต่จำนวนที่แทนค่าได้และใกล้เคียง 0.01 ที่สุดคือ
- 0.009999999776482582092285156250
อีกตัวอย่างหนึ่ง จำนวนที่ไม่สามารถแทนค่าได้อย่าง π (และ π/2) ทำให้การพยายามคำนวณ tan(π/2) จะไม่ได้ผลลัพธ์เป็นค่าอนันต์หรือแม้แต่ภาวะมากเกินเก็บ ฮาร์ดแวร์คอมพิวเตอร์มาตรฐานไม่สามารถคำนวณ tan(π/2) เพราะ tan(π/2) ไม่สามารถแทนค่าได้อย่างแม่นยำ เช่นในการคำนวณในภาษาซีดังนี้
/* เลขโดดจำนวนมากเพื่อให้แน่ใจว่าการประมาณจะถูกต้อง */
double pi = 3.1415926535897932384626433832795;
double z = tan(pi/2.0);
จะให้ผลลัพธ์เป็น 16331239353195370.0 แต่ในความเที่ยงหนึ่งเท่า (ใช้ฟังก์ชัน tanf) ผลลัพธ์จะเป็น −22877332.0
ในกรณีคล้ายกัน การพยายามคำนวณ sin(π) จะไม่ได้ค่าศูนย์ ผลลัพธ์ที่ได้โดยประมาณจะเท่ากับ 0.1225แม่แบบ:E ในความเที่ยงสองเท่า หรือ −0.8742แม่แบบ:E ในความเที่ยงหนึ่งเท่า[note 3]
การบวกและการคูณจำนวนจุดลอยตัวมีสมบัติการสลับที่ (a + b = b + a และ a × b = b × a) แต่ไม่จำเป็นว่าจะต้องมีสมบัติการเปลี่ยนหมู่ นั่นคือ (a + b) + c ไม่จำเป็นต้องเท่ากับ a + (b + c) เสมอไป เช่นตัวอย่างต่อไปนี้เป็นเลขคณิตฐานสิบเจ็ดหลัก กำหนดให้ a = 1234.567, b = 45.67834, c = 0.0004
|
กรณี (a + b) + c 1234.567 (a) + 45.67834 (b) ____________ 1280.24534 ปัดเศษเป็น 1280.245 1280.245 (a + b) + 0.0004 (c) ____________ 1280.2454 ปัดเศษเป็น 1280.245 |
กรณี a + (b + c) 45.67834 (b)
+ 0.0004 (c)
____________
45.67874
45.67874 (b + c) + 1234.567 (a) ____________ 1280.24574 ปัดเศษเป็น 1280.246 |
การบวกและการคูณจำนวนจุดลอยตัวก็ไม่จำเป็นต้องมีสมบัติการแจกแจง นั่นคือ (a + b) × c ไม่จำเป็นต้องเท่ากับ a × c + b × c เสมอไป จากตัวอย่างนี้กำหนดให้ a = 1234.567, b = 1.234567, c = 3.333333
|
กรณี (a + b) × c a + b = 1234.567 + 1.234567 = 1235.802
(a + b) × c
= 1235.802 × 3.333333 = 4119.340
|
กรณี a × c + b × c a × c = 1234.567 × 3.333333 = 4115.223
b × c = 1.234567 × 3.333333 = 4.115223
a × c + b × c
= 4115.223 + 4.115223 = 4119.338
|
นอกเหนือจากการสูญเสียนัยสำคัญ ความไม่สามารถในการแทนค่าจำนวนอาทิ π และ 0.1 ได้อย่างแม่นยำ และความไม่เที่ยงตรงเล็กน้อยอื่น ๆ ดังที่ได้กล่าวมาแล้ว ปรากฏการณ์ต่อไปนี้ก็อาจเกิดขึ้นได้เช่นกัน
- การตัดออกหมด: การลบระหว่างตัวถูกดำเนินการที่มีค่าเกือบเท่ากันอาจทำให้สูญเสียความถูกต้องไปมาก สิ่งนี้อาจเป็นปัญหาความแม่นยำที่พบบ่อยและร้ายแรง
- การแปลงเป็นจำนวนเต็มไม่เป็นไปตามที่คาด: เช่นการแปลง 63.0/9.0 เป็นจำนวนเต็มจะได้ 7 แต่การแปลง 0.63/0.09 อาจได้ 6 เนื่องจากการแปลงมักจะตัดเศษทิ้งมากกว่าปัดเศษ ฟังก์ชันพื้นและฟังก์ชันเพดานอาจให้คำตอบที่ต่างจากค่าคาดหวังอยู่หนึ่ง
- พิสัยของเลขชี้กำลังจำกัด: ผลลัพธ์อาจล้นเกินเก็บทำให้เกิดอนันต์ หรือน้อยเกินเก็บทำให้เกิดจำนวนต่ำกว่าบรรทัดฐานหรือศูนย์ ในกรณีเหล่านี้ความเที่ยงจะสูญเสียไป
- การทดสอบการหารที่ปลอดภัยเป็นปัญหา: การตรวจสอบว่าตัวหารไม่เป็นศูนย์ ไม่รับประกันได้ว่าผลหารจะไม่ล้นเกินเก็บ
- การทดสอบภาวะเท่ากันเป็นปัญหา: ลำดับการคำนวณสองลำดับที่เท่ากันในเชิงคณิตศาสตร์ อาจให้ผลลัพธ์ต่างกันในจำนวนจุดลอยตัว บ่อยครั้งที่โปรแกรมเมอร์ทำการเปรียบเทียบภายในความคลาดเคลื่อนยินยอมบางค่า (มักจะเป็นค่าคงตัวฐานสิบ ซึ่งโดยตัวมันเองไม่สามารถแทนค่าได้อย่างแม่นยำ) แต่ก็ไม่จำเป็นว่าปัญหานี้จะหมดไป
ความเที่ยงของเครื่องจักร
"ความเที่ยงของเครื่องจักร" หมายถึงปริมาณที่บ่งบอกความแม่นยำของระบบจำนวนจุดลอยตัว เป็นที่รู้จักในชื่อ การปัดเศษหน่วย (unit round-off) หรือ เอปไซลอนเครื่องจักร (machine epsilon) มักจะแสดงด้วย Εmach ค่าของมันขึ้นอยู่กับวิธีการปัดเศษเฉพาะที่ใช้
การปัดเศษเข้าหาศูนย์จะได้
ในขณะที่การปัดเศษสู่ค่าที่ใกล้ที่สุดจะได้
ปริมาณนี้มีความสำคัญเนื่องจากเป็นตัวจำกัดขอบเขตของ ค่าคลาดเคลื่อนสัมพัทธ์ ในการแทนค่าจำนวนจริงใด ๆ x ที่ไม่เป็นศูนย์ภายใต้พิสัยบรรทัดฐานของระบบจำนวนจุดลอยตัว ดังนี้
การลดผลกระทบของปัญหาความแม่นยำ
การใช้เลขคณิตจำนวนจุดลอยตัวอย่างตรงไปตรงมา นำไปสู่ปัญหาหลายอย่างดังที่กล่าวมาแล้วทั้งหมดข้างต้น การสร้างซอฟต์แวร์จุดลอยตัวที่คงทนถาวรอย่างสมบูรณ์จึงเป็นงานที่ซับซ้อน และความเข้าใจอันดีของการวิเคราะห์เชิงตัวเลขเป็นสิ่งสำคัญ
นอกจากการออกแบบโปรแกรมอย่างระมัดระวัง การจัดการอย่างรอบคอบโดยตัวแปลโปรแกรมก็จำเป็นเช่นกัน "การเพิ่มประสิทธิภาพ" บางอย่างที่ตัวแปลกระทำ (เช่นการจัดเรียงการดำเนินการใหม่) อาจไม่เป็นไปตามจุดมุ่งหมายของการพัฒนาซอฟต์แวร์ที่ทำงานได้ดี มีการถกเถียงเกี่ยวกับความล้มเหลวของตัวแปลโปรแกรมและการออกแบบภาษาในเรื่องนี้ ดูเพิ่มเติมที่แหล่งข้อมูลอื่น
เลขคณิตจุดลอยตัวฐานสอง เป็นสภาวการณ์ดีที่สุดเมื่อใช้วัดปริมาณในโลกแห่งความเป็นจริงซึ่งมีพิสัยของมาตราส่วนกว้าง (เช่นคาบดาราคติของไอโอหรือมวลของโปรตอน) แต่เป็นสภาวการณ์แย่ที่สุดเมื่อถูกคาดหวังให้จำลองความสัมพันธ์ของปริมาณในรูปของสายอักขระฐานสิบซึ่งมุ่งหวังว่าจะได้ค่าที่ถูกต้อง ตัวอย่างของกรณีหลังเช่นการคำนวณเชิงการเงิน ซอฟต์แวร์การเงินจึงมีความโน้มเอียงที่จะไม่ใช้การแทนจำนวนจุดลอยตัวฐานสองด้วยเหตุนี้[8] มาตรฐานจำนวนจุดลอยตัวฐานสิบของ IEEE 854 และชนิดตัวแปร "decimal" ของภาษาซีชาร์ปเป็นอาทิ ถูกออกแบบขึ้นเพื่อให้หลีกเลี่ยงปัญหาการแทนจำนวนจุดลอยตัวฐานสองที่ใช้กับค่าของเลขฐานสิบ ซึ่งมนุษย์จำเป็นต้องป้อนเข้าอย่างถูกต้อง และทำให้การคำนวณเลขคณิตได้ผลลัพธ์ตรงกับจำนวนฐานสิบที่คาดหวังเสมอ
ค่าคลาดเคลื่อนในเลขคณิตจุดลอยตัวอาจยิ่งสะสมมากขึ้น เมื่อขั้นตอนวิธีของการดำเนินการทางคณิตศาสตร์ถูกกระทำหลายครั้งมาก ตัวอย่างบางส่วนเช่น การหาตัวผกผันของเมทริกซ์ การคำนวณเวกเตอร์ลักษณะเฉพาะ และการแก้สมการเชิงอนุพันธ์ ขั้นตอนวิธีเหล่านี้จะต้องถูกออกแบบอย่างระมัดระวังมากเพื่อให้ทำงานได้ดี
ความคาดหวังต่าง ๆ ในทางคณิตศาสตร์อาจไม่สามารถทำให้เป็นจริงได้ในขอบเขตของการคำนวณจำนวนจุดลอยตัว ตัวอย่างเช่น เอกลักษณ์ทางคณิตศาสตร์อันเป็นที่ทราบโดยทั่วไปอาทิ หรือ ไม่สามารถไว้วางใจได้เมื่อปริมาณที่เกี่ยวข้องเป็นผลลัพธ์มาจากการคำนวณจำนวนจุดลอยตัว
การแก้ปัญหาทางเทคนิคโดยละเอียดสำหรับการเขียนซอฟต์แวร์จุดลอยตัวคุณภาพสูงเป็นเรื่องเกินขอบเขตของบทความนี้ ผู้อ่านกรุณาดูเพิ่มเติมในแหล่งอ้างอิงที่ท้ายบทความ ต่อไปนี้จะอธิบายเทคนิคอย่างง่ายเพียงเล็กน้อย
การทดสอบภาวะเท่ากัน (if (x==y) ...) โดยปกติไม่เป็นที่แนะนำเมื่อความคาดหวังขึ้นอยู่กับผลลัพธ์ทางคณิตศาสตร์ การทดสอบเช่นนี้บางครั้งถูกแทนที่ด้วยการเปรียบเทียบแบบ "คลุมเครือ" (if (abs(x-y) < epsilon) ... ซึ่ง epsilon มีค่าเล็กน้อยอย่างเพียงพอและถูกปรับให้เหมาะสมกับการใช้งานเช่น 1.0E−13) การตัดสินใจกระทำเช่นนี้แตกต่างหลากหลายอย่างมาก การจัดระเบียบรหัสดังกล่าวก็มักจะดีกว่าแม้การทดสอบดังกล่าวไม่มีความจำเป็น
การตระหนักถึงการสูญเสียเลขนัยสำคัญที่สามารถเกิดขึ้นก็มีประโยชน์ ตัวอย่างเช่น ถ้าเราบวกจำนวนขนาดใหญ่มากกับจำนวนขนาดเล็กมากเมื่อเปรียบเทียบกับผลบวก จะทำให้เกิดการสูญเสียเลขนัยสำคัญ การบวกโดยทั่วไปจะเป็นเหมือนเช่นนี้
3253.671 + 3.141276 -------- 3256.812
สามหลักสุดท้ายของตัวบวกสูญเสียไปในผลลัพธ์ สมมติว่าเราต้องการบวกจำนวนหลายจำนวนซึ่งทุกจำนวนมีค่าประมาณ 3 หลังจากบวกเข้าไป 1000 ครั้ง ผลบวกจะเพิ่มขึ้นประมาณ 3000 เลขนัยสำคัญที่สูญไปมิได้ถูกนำกลับมาเพื่อคำนวณใหม่ ขั้นตอนวิธีการบวกของคาฮานอาจใช้เพื่อลดค่าคลาดเคลื่อนนี้ได้
การคำนวณอาจถูกปรับปรุงใหม่ในทางคณิตศาสตร์ที่เทียบเท่าแต่มีแนวโน้มของความคลาดเคลื่อนน้อยกว่า ตัวอย่างเช่น อาร์คิมิดีสประมาณค่า π โดยการคำนวณความยาวรอบรูปของรูปหลายเหลี่ยมที่บรรจุภายในและภายนอกรูปวงกลม โดยเริ่มที่รูปหกเหลี่ยมแล้วเพิ่มจำนวนด้านทีละสองเท่า สูตรเวียนเกิดของรูปหลายเหลี่ยมภายนอกรูปวงกลมคือ
- รูปแบบที่หนึ่ง: ; รูปแบบที่สอง:
- ลู่เข้าเมื่อ
ในที่นี้จะคำนวณด้วยเลขคณิต "double" แบบ IEEE (ซิกนิฟิแคนด์ที่มีความเที่ยง 53 บิต)
i 6 × 2i × ti รูปแบบที่หนึ่ง 6 × 2i × ti รูปแบบที่สอง 0 แม่แบบ:สี.4641016151377543863 แม่แบบ:สี.4641016151377543863 1 แม่แบบ:สี.2153903091734710173 แม่แบบ:สี.2153903091734723496 2 แม่แบบ:สี596599420974940120 แม่แบบ:สี596599420975006733 3 แม่แบบ:สี60862151314012979 แม่แบบ:สี60862151314352708 4 แม่แบบ:สี27145996453136334 แม่แบบ:สี27145996453689225 5 แม่แบบ:สี8730499801259536 แม่แบบ:สี8730499798241950 6 แม่แบบ:สี6627470548084133 แม่แบบ:สี6627470568494473 7 แม่แบบ:สี6101765997805905 แม่แบบ:สี6101766046906629 8 แม่แบบ:สี70343230776862 แม่แบบ:สี70343215275928 9 แม่แบบ:สี37488171150615 แม่แบบ:สี37487713536668 10 แม่แบบ:สี9278733740748 แม่แบบ:สี9273850979885 11 แม่แบบ:สี7256228504127 แม่แบบ:สี7220386148377 12 แม่แบบ:สี717412858693 แม่แบบ:สี707019992125 13 แม่แบบ:สี189011456060 แม่แบบ:สี78678454728 14 แม่แบบ:สี717412858693 แม่แบบ:สี46593073709 15 แม่แบบ:สี19358822321783 แม่แบบ:สี8571730119 16 แม่แบบ:สี717412858693 แม่แบบ:สี6566394222 17 แม่แบบ:สี810075796233302 แม่แบบ:สี6065061913 18 แม่แบบ:สี717412858693 แม่แบบ:สี939728836 19 แม่แบบ:สี4061547378810956 แม่แบบ:สี908393901 20 แม่แบบ:สี05434924008406305 แม่แบบ:สี900560168 21 แม่แบบ:สี00068646912273617 แม่แบบ:สี8608396 22 แม่แบบ:สี349453756585929919 แม่แบบ:สี8122118 23 แม่แบบ:สี00068646912273617 แม่แบบ:สี95552 24 แม่แบบ:สี.2245152435345525443 แม่แบบ:สี68907 25 แม่แบบ:สี62246 26 แม่แบบ:สี62246 27 แม่แบบ:สี62246 28 แม่แบบ:สี62246 ค่าที่แท้จริงคือ แม่แบบ:สี
ในขณะที่รูปแบบทั้งสองของสูตรเวียนเกิดเทียบเท่ากันอย่างชัดเจน สูตรแรกมีการลบ 1 ด้วยจำนวนที่มีค่าใกล้เคียง 1 อย่างสุดขีด จนทำให้เกิดการตัดออกหมดขนานใหญ่ สังเกตว่าการเวียนเกิดซ้ำ ๆ จะให้ผลที่แม่นยำมากขึ้นในตอนแรก แต่ภายหลังก็ลดลง ไม่สามารถมีค่าที่แม่นยำมากกว่า 8 หลัก แม้จะใช้เลขคณิต 53 บิตที่สามารถจัดการกับความเที่ยงประมาณ 16 หลัก ในอีกทางหนึ่ง สูตรที่สองของการเวียนเกิดให้ผลลัพธ์ลู่เข้าที่แม่นยำถึง 15 หลัก
เชิงอรรถ
- ↑ ฮาร์ดแวร์คอมพิวเตอร์ไม่จำเป็นต้องคำนวณแล้วได้ค่าที่ถูกต้องแม่นยำ มันเพียงต้องสร้างผลลัพธ์ที่เทียบเท่ากันซึ่งปัดเศษแล้ว แม้ว่าผลที่คำนวณได้เป็นผลลัพธ์ที่มีความเที่ยงอนันต์
- ↑ ความซับซ้อนอย่างมหาศาลของขั้นตอนวิธีการหารสมัยใหม่ครั้งหนึ่ง นำมาซึ่งความผิดพลาดอันโด่งดัง ชิปอินเทล เพนเทียม รุ่นแรก ๆ มาพร้อมกับชุดคำสั่งการหารที่ให้ผลลัพธ์ไม่ถูกต้องเล็กน้อย แต่ก็มีโอกาสเกิดขึ้นได้ยาก คอมพิวเตอร์จำนวนมากขายออกไปก่อนที่จะค้นพบความผิดพลาดนี้ มีการพัฒนาคอมไพเลอร์รุ่นซ่อมแซมหลายรุ่นเพื่อให้สามารถหลีกเลี่ยงกรณีที่ผิดพลาด จนกระทั่งคอมพิวเตอร์ที่บกพร่องทั้งหลายถูกเปลี่ยนแทนที่ ดูรายละเอียดได้ที่ บั๊ก FDIV ของเพนเทียม
- ↑ แต่การพยายามคำนวณ cos(π) จะได้ค่า −1 อย่างแม่นยำ เนื่องจากอนุพันธ์ของฟังก์ชัน cos จะมีค่าเข้าใกล้ศูนย์ เมื่ออาร์กิวเมนต์มีค่าเข้าใกล้ π ความไม่แม่นยำของอาร์กิวเมนต์มีผลกระทบเล็กน้อยมากเมื่อเทียบกับช่องว่างจำนวนจุดลอยตัวทางซ้ายและทางขวาของค่า −1 หลังจากปัดเศษแล้วผลลัพธ์จึงแม่นยำ
อ้างอิง
แหล่งข้อมูลอื่น
- Kahan, William and Darcy, Joseph (2001). How Java’s floating-point hurts everyone everywhere. Retrieved September 5, 2003 from http://www.cs.berkeley.edu/~wkahan/JAVAhurt.pdf.
- The pitfalls of verifying floating-point computations, by David Monniaux, also printed in ACM Transactions on programming languages and systems (TOPLAS), May 2008: a compendium of non-intuitive behaviours of floating-point on popular architectures, with implications for program verification and testing
- Survey of Floating-Point Formats บทสรุปอย่างสั้นของรูปแบบจำนวนจุดลอยตัวที่เคยมีใช้ในอดีต
หนังสืออ่านเพิ่มเติม
- What Every Computer Scientist Should Know About Floating-Point Arithmetic, by David Goldberg, published in the March, 1991 issue of Computing Surveys.
- Donald Knuth. The Art of Computer Programming, Volume 2: Seminumerical Algorithms, Third Edition. Addison-Wesley, 1997. ISBN 0-201-89684-2. Section 4.2: Floating Point Arithmetic, pp. 214–264.
- Press et al. Numerical Recipes in C++. The Art of Scientific Computing, ISBN 0-521-75033-4.