ในทางคอมพิวเตอร์ จำนวนจุดลอยตัว (อังกฤษ: floating point) คือระบบแทนจำนวนชนิดหนึ่ง ซึ่งจำนวนนั้นอาจมีขนาดใหญ่หรือขนาดเล็กเกินกว่าที่จะแทนด้วยจำนวนเต็ม เนื่องจากจำนวนต่าง ๆ สามารถเขียนแทนด้วยเลขนัยสำคัญ (mantissa) จำนวนหนึ่งโดยประมาณ และเปลี่ยนสเกลด้วยเลขชี้กำลัง (exponent) ฐานของสเกลปกติจะเป็น 2, 10 หรือ 16 เป็นต้น จำนวนทั่วไปจึงสามารถเขียนให้อยู่ในรูปแบบนี้ได้

Z3 คอมพิวเตอร์ฐานสองเชิงกลที่สามารถโปรแกรมและดำเนินการทางคณิตศาสตร์ได้เครื่องแรก (จัดแสดงต่อสาธารณะที่พิพิธภัณฑ์เยอรมันในเมืองมิวนิก
ตัวอย่างแสดงถึงการแทนจำนวนจุดลอยตัวโดยแบ่งเป็นการเก็บค่าเลขนัยสำคัญและเลขชี้กำลัง
เลขนัยสำคัญ × ฐาน เลขชี้กำลัง

คำว่า จุดลอยตัว จึงหมายถึงจุดฐาน (จุดทศนิยม หรือในคอมพิวเตอร์คือ จุดทวินิยม[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×105 วินาที

จำนวนจุดลอยตัวเป็นแนวคิดที่คล้ายกับสัญกรณ์คณิตศาสตร์ จึงประกอบด้วยสองส่วนตามหลักเหตุผล

  • สายอักขระของเลขโดดที่มีเครื่องหมายบวกลบ ตามความยาวและฐานที่กำหนด ส่วนนี้เรียกว่า ซิกนิฟิแคนด์ (significand) หรือบางครั้งเรียกว่า แมนทิสซา (mantissa) หรือ สัมประสิทธิ์ จุดฐานนั้นไม่ได้รวมอยู่ด้วย แต่อาจสมมติโดยนัยว่าวางอยู่ที่ใดที่หนึ่งในซิกนิฟิแคนด์ ซึ่งบ่อยครั้งอยู่ก่อนหรือหลังเลขโดดที่มีนัยสำคัญมากสุด หรืออยู่ทางขวาสุดก็ได้ (บทความนี้จะใช้ข้อตกลงว่าจุดฐานอยู่หลังเลขโดดที่มีนัยสำคัญมากสุด) ความยาวของซิกนิฟิแคนด์เป็นตัวพิจารณาความเที่ยงของจำนวนที่ใช้แทน
  • เลขชี้กำลังจำนวนเต็มที่มีเครื่องหมายบวกลบ หรือเรียกว่า แคแรกเทอริสติก (characteristic) หรือสเกล ซึ่งเป็นตัวดัดแปรขนาดมากน้อยของจำนวน

ซิกนิฟิแคนด์ คูณด้วย ฐาน ที่ยกกำลังด้วย เลขชี้กำลัง จะเทียบเท่ากับการเลื่อนจุดฐานจากตำแหน่งสมมติ ไปเป็นจำนวนหลักเท่ากับค่าของเลขชี้กำลัง โดยเลื่อนไปทางขวาถ้าเลขชี้กำลังเป็นบวกหรือไปทางซ้ายถ้าเลขชี้กำลังเป็นลบ

หากอธิบายด้วยเลขฐานสิบอันเป็นสัญกรณ์ที่คุ้นเคย จำนวน 152853.5047 ซึ่งมีเลขโดดฐานสิบ ความเที่ยงสิบหลัก การแทนจำนวนจะได้ 1528535047 เป็นซิกนิฟิแคนด์ และเลขชี้กำลังเป็น 5 (โดยจุดฐานถูกสมมติขึ้นที่หลังเลข 1 ซึ่งเป็นเลขโดดที่มีนัยสำคัญมากสุด) และเพื่อที่จะเรียกคืนค่าแท้จริง จะเติมจุดทศนิยมที่หลังเลขโดดตัวแรกของซิกนิฟิแคนด์ แล้วนำไปคูณด้วย 105 จนได้ 1.528535047×105 ซึ่งนั่นก็คือจำนวน 152853.5047 ในการเก็บบันทึกจำนวนเช่นนี้ ฐาน 10 ไม่จำเป็นต้องเก็บบันทึกไปด้วย เนื่องจากมันมีใช้เหมือนกันในทุก ๆ จำนวน และสามารถอนุมานได้ในภายหลัง จำนวนนี้จึงอาจเขียนอย่างง่ายได้เป็น 1.528535047 E 5 ซึ่ง "E" กำหนดให้หมายถึง "คูณด้วยสิบยกกำลัง..." เช่นเดียวกับข้อตกลงอันเป็นที่ทราบ

หากเขียนเป็นสัญลักษณ์ ค่าสุดท้ายที่ได้ออกมาคือ

 

เมื่อ s คือซิกนิฟิแคนด์ที่เติมจุดฐานสมมติเข้าไปแล้ว b คือฐาน และ e คือเลขชี้กำลัง

หรือเทียบเท่ากับประโยคนี้

 

เมื่อ s คือจำนวนเต็มจากซิกนิฟิแคนด์ทั้งหมดโดยไม่พิจารณาจุดฐานสมมติ ส่วน p คือความเที่ยง (precision) หมายถึงจำนวนหลักของซิกนิฟิแคนด์

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

วิธีการที่ซิกนิฟิแคนด์ เลขชี้กำลัง และบิตเครื่องหมายถูกเก็บบันทึกภายในคอมพิวเตอร์ขึ้นอยู่กับวิธีการทำให้เกิดผล รูปแบบปกติของ 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)
  • จำนวนบางจำนวนไม่สามารถแทนได้อย่างแม่นยำในจำนวนจุดลอยตัวไม่ว่าจะกำหนดความเที่ยงเท่าใด (เช่น 1/3 และ 0.1) แพกเกจซอฟต์แวร์ที่ดำเนินการเลขคณิตจำนวนตรรกยะ จะแทนที่จำนวนต่าง ๆ เป็นเศษส่วนโดยมีตัวเศษและตัวส่วนเป็นจำนวนเต็ม จึงสามารถให้ผลเป็นจำนวนตรรกยะใด ๆ ได้อย่างถูกต้อง แพกเกจเช่นนั้นจำเป็นต้องใช้เลขคณิตสำหรับจำนวนขนาดใหญ่ (bignum) สำหรับจำนวนเต็มแต่ละจำนวน
  • ระบบพีชคณิตคอมพิวเตอร์ อย่างเช่นแมทเทอแมติกาหรือแมกซิมา สามารถจัดการกับจำนวนอตรรกยะอย่างเช่น π หรือ √3 ด้วยวิธีการแบบรูปนัยอย่างสมบูรณ์ โดยไม่ต้องยุ่งกับการเข้ารหัสซิกนิฟิแคนด์ โปรแกรมเหล่านี้จะคำนวณนิพจน์อย่างเช่น sin 3π ได้อย่างแม่นยำ เพราะโปรแกรมทราบถึงคณิตศาสตร์ที่เป็นรากฐาน
  • การแทนจำนวนโดยใช้พื้นฐานจากลอการิทึมธรรมชาติบางครั้งพบได้ในโปรแกรมประยุกต์ในเอฟพีจีเอ ที่ซึ่งการดำเนินการเลขคณิตส่วนใหญ่เป็นการคูณและการหาร[2] แนวทางนี้มีความเที่ยงสำหรับจำนวนขนาดเล็กและรองรับช่วงค่ากว้าง เช่นเดียวกับจำนวนจุดลอยตัว

พิสัยของจำนวนจุดลอยตัว แก้

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

0.12 × 0.12 = 0.0144

เมื่อเขียนแทนในระบบจำนวนจุดลอยตัวฐานสิบ ซึ่งมีเลขโดดสามหลัก จะได้

(1.2×10−1) × (1.2×10−1) = (1.44×10−2)

ในขณะที่ระบบจำนวนจุดตรึงที่มีจุดทศนิยมอยู่ทางซ้ายสุด ซึ่งมีเลขโดดสามหลักเช่นกัน จะได้

0.120 × 0.120 = 0.014

จะเห็นว่าผลลัพธ์ของจำนวนจุดตรึงสูญหายไปบางส่วน เพราะไม่มีที่อยู่สำหรับเลขโดดที่เกินมา และจุดทศนิยม "ลอยตัว" ไม่ได้ภายในสายอักขระของเลขโดด

พิสัยของจำนวนจุดลอยตัวจึงขึ้นอยู่กับจำนวนบิตหรือเลขโดดที่ใช้สำหรับแทนซิกนิฟิแคนด์ (เลขนัยสำคัญของจำนวน) และเลขชี้กำลัง การแทนจำนวนจุดลอยตัวฐานสองขนาดความเที่ยงสองเท่า (64 บิต) ในระบบคอมพิวเตอร์ทั่วไป จะมีสัมประสิทธิ์ 53 บิต (ซึ่งบิตแรกสุดไม่ต้องเก็บบันทึก) เลขชี้กำลัง 11 บิต และบิตเครื่องหมายอีกหนึ่งบิต จำนวนจุดลอยตัวที่เป็นค่าบวกในรูปแบบนี้จึงมีพิสัยอยู่ที่ประมาณ 10−308 ถึง 10308 (ค่า 308 มาจาก 1023 × log10 (2) โดยประมาณ และพิสัยของเลขชี้กำลังอยู่ในช่วง [−1022, 1023]) พิสัยโดยรวมทั้งหมดของรูปแบบนี้จึงเก็บบันทึกได้ตั้งแต่ −10308 ไปจนถึง +10308 (ดูเพิ่มที่ 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)

ประวัติ แก้

 
คอนรัด ทซูเซอ สถาปนิกผู้ประดิษฐ์คอมพิวเตอร์ฐานสองเชิงกลที่สามารถโปรแกรมได้เครื่องแรก ซึ่งทำงานด้วยจำนวนจุดลอยตัวฐานสอง 22 บิต

เมื่อ พ.ศ. 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 ยังคงใช้รูปแบบของมันเอง

ความเที่ยงต่าง ๆ ของจำนวนจุดลอยตัวตาม IEEE 754

16 บิต: ครึ่งเท่า (ฐานสอง 16 บิต)
32 บิต: หนึ่งเท่า (ฐานสอง 32 บิต), ฐานสิบ 32 บิต
64 บิต: สองเท่า (ฐานสอง 64 บิต), ฐานสิบ 64 บิต
128 บิต: สี่เท่า (ฐานสอง 128 บิต), ฐานสิบ 128 บิต

มาตรฐานนี้กำหนดรูปแบบหลายชนิดที่เกี่ยวข้องอย่างใกล้ชิด ต่างกันที่รายละเอียดเพียงเล็กน้อย มีห้ารูปแบบเรียกว่า รูปแบบพื้นฐาน และมีอีกสองรูปแบบเป็นรูปแบบที่ใช้อย่างกว้างขวางในฮาร์ดแวร์คอมพิวเตอร์และภาษาโปรแกรมโดยเฉพาะได้แก่

  • ความเที่ยงหนึ่งเท่า (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) ซึ่งต่างจากศูนย์ธรรมดา และค่าไม่ใช่จำนวน (อังกฤษ: NaN (Not a Number))

การเปรียบเทียบจำนวนจุดลอยตัวก็ได้กำหนดไว้ในมาตรฐาน 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 ระบุค่าพิเศษอีกอย่างหนึ่งคือค่าไม่ใช่จำนวน (อังกฤษ: NaN (Not a Number)) เพื่อคืนค่าเป็นผลลัพธ์สำหรับการดำเนินการที่ "ไม่สมเหตุสมผล" ตัวอย่างเช่น 0/0, ∞×0, sqrt(−1) เป็นต้น NaN แท้จริงแล้วมีสองชนิดคือ signaling และ quiet การใช้ signaling NaN ในการดำเนินการเลขคณิตใด ๆ (รวมทั้งการเปรียบเทียบเชิงจำนวน) ทำให้เกิดสิ่งผิดปรกติ "ไม่สมเหตุสมผล" ส่วนการใช้ quiet NaN จะได้ผลลัพธ์เป็น NaN เท่านั้นโดยไม่เกิดสิ่งผิดปรกติ

การแทนค่า NaN ที่กำหนดโดยมาตรฐาน มีบางบิตที่ไม่ระบุซึ่งอาจใช้เข้ารหัสชนิดของข้อผิดพลาดได้ แต่ก็ไม่มีมาตรฐานสำหรับการเข้ารหัสนี้ ในทางทฤษฎี signaling NaN สามารถใช้กับระบบขณะทำงาน (runtime system) เพื่อขยายจำนวนจุดลอยตัวด้วยค่าพิเศษอื่น โดยไม่ต้องชะลอการคำนวณกับจำนวนธรรมดา แม้ว่าการขยายเช่นนั้นดูเหมือนว่าไม่เป็นสิ่งปกติสามัญ

จำนวนที่แทนได้ การแปลง และการปัดเศษ แก้

โดยธรรมชาติแล้ว จำนวนทุกจำนวนที่สามารถเขียนให้อยู่ในรูปแบบจำนวนจุดลอยตัว เป็นจำนวนตรรกยะที่มีจุดฐานรู้จบในฐานที่สัมพันธ์กัน (เช่นทศนิยมรู้จบในฐานสิบ หรือทวินิยมรู้จบในฐานสอง) ส่วนจำนวนอตรรกยะอย่างเช่น π หรือ √2 หรือจำนวนตรรกยะที่มีจุดฐานไม่รู้จบต้องใช้เป็นค่าประมาณ จำนวนของเลขโดด (หรือบิต) ของความเที่ยงก็เป็นตัวจำกัดเซตของจำนวนตรรกยะที่สามารถแทนค่าได้อย่างแม่นยำ ตัวอย่างเช่น จำนวน 123456789 จะไม่สามารถแทนค่าได้อย่างแม่นยำถ้ามีความเที่ยงบนเลขโดดฐานสิบเพียงแปดหลัก เป็นต้น

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

จำนวนตรรกยะไม่จำเป็นว่าต้องมีจุดฐานรู้จบในฐานที่สัมพันธ์กัน ตัวอย่างเช่น จำนวน 1/2 ในฐานสิบเป็นทศนิยมรู้จบ (0.5) ในขณะที่ 1/3 เป็นทศนิยมไม่รู้จบ (0.333…) จำนวนตรรกยะในฐานสองที่มีตัวส่วนเป็นกำลังของ 2 เท่านั้นที่เป็นทวินิยมรู้จบ (เช่น 1/2 หรือ 3/16) จำนวนตรรกยะที่มีตัวส่วนเป็นตัวประกอบเฉพาะอื่นนอกจาก 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         (หลังจากปัดเศษ/ทำให้เป็นบรรทัดฐาน)

อีกตัวอย่างหนึ่งของปัญหาการสูญเสียนัยสำคัญ เกิดขึ้นในการลบสองจำนวนที่มีค่าใกล้เคียงกัน จากตัวอย่างนี้ e = 5; s = 1.234571 และ e = 5; s = 1.234567 เป็นการแทนค่าของจำนวนตรรกยะ 123457.1467 และ 123456.659 ตามลำดับ

  e=5;  s=1.234571
− e=5;  s=1.234567
----------------
  e=5;  s=0.000004
  e=−1; s=4.000000 (หลังจากปัดเศษ/ทำให้เป็นบรรทัดฐาน)

การแทนค่าที่ดีที่สุดของผลต่างนี้ควรเป็น e = −1; s = 4.877000 ซึ่งต่างจากผลลัพธ์ e = −1; s = 4.000000 อยู่มากกว่า 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 ฐานสิบ ดังที่เคยกล่าวไว้ว่าแทนค่าได้เป็น e = −4; s = 110011001100110011001101 มีค่าที่แท้จริงเท่ากับ

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×10−15 ในความเที่ยงสองเท่า หรือ −0.8742×10−7 ในความเที่ยงหนึ่งเท่า[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   3.4641016151377543863      3.4641016151377543863
 1   3.2153903091734710173      3.2153903091734723496
 2   3.1596599420974940120      3.1596599420975006733
 3   3.1460862151314012979      3.1460862151314352708
 4   3.1427145996453136334      3.1427145996453689225
 5   3.1418730499801259536      3.1418730499798241950
 6   3.1416627470548084133      3.1416627470568494473
 7   3.1416101765997805905      3.1416101766046906629
 8   3.1415970343230776862      3.1415970343215275928
 9   3.1415937488171150615      3.1415937487713536668
10   3.1415929278733740748      3.1415929273850979885
11   3.1415927256228504127      3.1415927220386148377
12   3.1415926717412858693      3.1415926707019992125
13   3.1415926189011456060      3.1415926578678454728
14   3.1415926717412858693      3.1415926546593073709
15   3.1415919358822321783      3.1415926538571730119
16   3.1415926717412858693      3.1415926536566394222
17   3.1415810075796233302      3.1415926536065061913
18   3.1415926717412858693      3.1415926535939728836
19   3.1414061547378810956      3.1415926535908393901
20   3.1405434924008406305      3.1415926535900560168
21   3.1400068646912273617      3.1415926535898608396
22   3.1349453756585929919      3.1415926535898122118
23   3.1400068646912273617      3.1415926535897995552
24   3.2245152435345525443      3.1415926535897968907
25                              3.1415926535897962246
26                              3.1415926535897962246
27                              3.1415926535897962246
28                              3.1415926535897962246
               ค่าที่แท้จริงคือ 3.141592653589793238462643383...

ในขณะที่รูปแบบทั้งสองของสูตรเวียนเกิดเทียบเท่ากันอย่างชัดเจน สูตรแรกมีการลบ 1 ด้วยจำนวนที่มีค่าใกล้เคียง 1 อย่างสุดขีด จนทำให้เกิดการตัดออกหมดขนานใหญ่ สังเกตว่าการเวียนเกิดซ้ำ ๆ จะให้ผลที่แม่นยำมากขึ้นในตอนแรก แต่ภายหลังก็ลดลง ไม่สามารถมีค่าที่แม่นยำมากกว่า 8 หลัก แม้จะใช้เลขคณิต 53 บิตที่สามารถจัดการกับความเที่ยงประมาณ 16 หลัก ในอีกทางหนึ่ง สูตรที่สองของการเวียนเกิดให้ผลลัพธ์ลู่เข้าที่แม่นยำถึง 15 หลัก

เชิงอรรถ แก้

  1. ฮาร์ดแวร์คอมพิวเตอร์ไม่จำเป็นต้องคำนวณแล้วได้ค่าที่ถูกต้องแม่นยำ มันเพียงต้องสร้างผลลัพธ์ที่เทียบเท่ากันซึ่งปัดเศษแล้ว แม้ว่าผลที่คำนวณได้เป็นผลลัพธ์ที่มีความเที่ยงอนันต์
  2. ความซับซ้อนอย่างมหาศาลของขั้นตอนวิธีการหารสมัยใหม่ครั้งหนึ่ง นำมาซึ่งความผิดพลาดอันโด่งดัง ชิปอินเทล เพนเทียม รุ่นแรก ๆ มาพร้อมกับชุดคำสั่งการหารที่ให้ผลลัพธ์ไม่ถูกต้องเล็กน้อย แต่ก็มีโอกาสเกิดขึ้นได้ยาก คอมพิวเตอร์จำนวนมากขายออกไปก่อนที่จะค้นพบความผิดพลาดนี้ มีการพัฒนาคอมไพเลอร์รุ่นซ่อมแซมหลายรุ่นเพื่อให้สามารถหลีกเลี่ยงกรณีที่ผิดพลาด จนกระทั่งคอมพิวเตอร์ที่บกพร่องทั้งหลายถูกเปลี่ยนแทนที่ ดูรายละเอียดได้ที่ บั๊ก FDIV ของเพนเทียม
  3. แต่การพยายามคำนวณ cos(π) จะได้ค่า −1 อย่างแม่นยำ เนื่องจากอนุพันธ์ของฟังก์ชัน cos จะมีค่าเข้าใกล้ศูนย์ เมื่ออาร์กิวเมนต์มีค่าเข้าใกล้ π ความไม่แม่นยำของอาร์กิวเมนต์มีผลกระทบเล็กน้อยมากเมื่อเทียบกับช่องว่างจำนวนจุดลอยตัวทางซ้ายและทางขวาของค่า −1 หลังจากปัดเศษแล้วผลลัพธ์จึงแม่นยำ

อ้างอิง แก้

  1. 310212: Introduction to Computer Science – การจัดเก็บข้อมูล ตอนที่ 3[ลิงก์เสีย]. คณะวิทยาการสารสนเทศ มหาวิทยาลัยบูรพา.
  2. Haohuan Fu; Oskar Mencer; Wayne Luk (December 2006). "Comparing Floating-point and Logarithmic Number Representations for Reconfigurable Acceleration". IEEE Conference on Field Programmable Technology: 337. doi:10.1109/FPT.2006.270342.
  3. "Konrad Zuse's Legacy: The Architecture of the Z1 and Z3" (PDF). IEEE Annals of the History of Computing. 19 (2): 5–15. 1997.
  4. Severance, Charles (20 Feb 1998). "An Interview with the Old Man of Floating-Point".
  5. "openEXR". คลังข้อมูลเก่าเก็บจากแหล่งเดิมเมื่อ 2013-05-08. สืบค้นเมื่อ 2010-10-02.
  6. "IEEE-754 Floating-Point Conversion From 32-bit Hexadecimal Representation To Decimal Floating-Point". คลังข้อมูลเก่าเก็บจากแหล่งเดิมเมื่อ 2010-09-30. สืบค้นเมื่อ 2010-10-02.
  7. Goldberg, David (1991). "What Every Computer Scientist Should Know About Floating-Point Arithmetic". ACM Computing Surveys. 23: 5–48. doi:10.1145/103162.103163. สืบค้นเมื่อ 2010-09-02.
  8. General Decimal Arithmetic

แหล่งข้อมูลอื่น แก้

  • 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 บทสรุปอย่างสั้นของรูปแบบจำนวนจุดลอยตัวที่เคยมีใช้ในอดีต

หนังสืออ่านเพิ่มเติม แก้