Floating-point exception เกิดขึ้นเมื่อซอฟต์แวร์พยายามดำเนินการผิดปกติบนตัวเลข ประเภทของ exception นี้เกิดขึ้นเมื่อผู้ใช้พยายามดำเนินการ invalid operations เช่น การหารด้วยศูนย์ การหารจำนวนลบด้วยจำนวนคู่ การหารรากที่สองของจำนวนลบ หรือ overflow ของการคำนวณที่เกินขีดจำกัดของ double data type
ใน C++ “SIGFPE” signal handler จัดการ floating point exceptions (FPEs) เมื่อผู้ใช้พยายามดำเนินการที่กล่าวมา signal handler นี้จะถูกเรียก หลังจากที่ signal handler เข้ามาติดมือ มันจะพิมพ์ข้อความข้อผิดพลาดไปยัง standard output และหยุดโปรแกรม
ทำไม Floating-Point Exceptions จึงเกิดขึ้น?
Floating point exceptions อาจเกิดจาก programming errors หรือเมื่อโปรแกรมพยายามประมวลผลค่าที่ไม่อยู่ในข้อกำหนด ตัวอย่างเช่น หากโปรแกรมพยายามหารจำนวนเต็มด้วยศูนย์ หรือหากโปรแกรมพยายามหารรากที่สองของจำนวนลบ floating point exception จะเกิดขึ้น นอกจากนี้ บาง floating-point exceptions อาจเกิดจาก processor misdetections
ปัจจัยหลายอย่าง เช่น การดำเนินการที่ไม่เหมาะสม underflow, overflow, division by zero และ accuracy อาจทำให้เกิด floating-point exception เราจะครอบคลุมข้อโต้แย้งเหล่านี้ทีละอย่างในส่วนนี้
1: Illegal Operation
เมื่อผู้ใช้ลืมแสดงการดำเนินการหรือการดำเนินการไม่มีค่าทางคณิตศาสตร์ โปรแกรมจะล้มเหลวในการดำเนินการเนื่องจาก invalid operation นี่รวมถึงการคำนวณเช่น square root และ logarithm ของจำนวนลบ ตัวอย่างเช่น แม้ว่าจะเป็นไปได้ที่จะหารรากที่สองของจำนวนลบเมื่อจัดการกับ complex numbers แต่ไม่มีกลไกคอมพิวเตอร์ที่สามารถแสดงได้
นอกจากนี้ incorrect operation จะเกิดขึ้นหากซอฟต์แวร์ดำเนินการ floating-point operation บน integer-only location เนื่องจาก mismatch ระหว่างการดำเนินการที่คุณพยายามดำเนินการบนข้อมูล (floating-point operation) และข้อมูลที่จัดเก็บ (integer)
2: Zero division
Floating-point exception จะถูกโยนหากคุณพยายามหารจำนวนเต็มด้วยศูนย์ สิ่งเดียวกันเกิดขึ้นเมื่อคุณพยายามหารด้วย NaN หรือ infinity นี่คือตัวอย่างบางอย่าง: 1/0, log(0)
3: Overflow
เมื่อการดำเนินการส่งคืนค่าที่อยู่นอกช่วงที่คาดไว้ overflow exception จะเกิดขึ้น ค่าจะมากกว่าหรือน้อยกว่าค่าที่นิยามได้เล็กที่สุด ตามข้อความนี้
4: Underflow
Underflow เกิดขึ้นเมื่อการคำนวณให้ผลลัพธ์ที่น้อยกว่าที่ data type สามารถจัดเก็บได้
5: Inexact
เมื่อผลลัพธ์ของการดำเนินการแตกต่างจากสิ่งที่คาดหวัง นี่คือ inexact exception เมื่อดำเนินการด้วย unbound precision และ exponent range จะเกิดขึ้น
ในบางกรณี สถานการณ์แบบนี้สามารถจัดการได้อย่างเหมาะสม ตัวอย่างเช่น เมื่อโปรแกรมพยายามหารตัวเลขด้วยศูนย์ มันโดยทั่วไปจะดีกว่าที่จะส่งคืนข้อความข้อผิดพลาดและจบโปรแกรมอย่างสงบ แทนที่จะปล่อยให้โปรแกรม crash
#include
#include
using namespace std;
float Div(float num, float den)
{
if (den == 0) {
throw runtime_error("Math error: Attempted to divide by 0\n");
}
return (num / den);
}
int main()
{
float num, denom, result;
num = 10;
denom = 0;
try {
result = Div(num, denom);
cout << "The quotient is " << result << endl;
}
catch (runtime_error& e) {
cout << "Exception occurred" << endl << e.what();
}
}
ในโค้ดนี้ ฟังก์ชัน Div ถูกเรียกโดย try block ภายใน main หาก denom ไม่เท่ากับ ศูนย์ ฟังก์ชัน Div จะส่งคืนผลหาร หากเป็นศูนย์ runtime error exception จะถูกโยน ก่อนที่จะเรียก what function ด้วย runtime error object e catch block จะจับ exception นี้และพิมพ์ข้อความ “Error occurred” มันถูกใช้เพื่อระบุ exception คลาส Standard exception ซึ่งอธิบายใน header file stdexcept มี virtual function ชื่อ what() ข้อความ “Math error: Attempted to divide by 0” จะถูกพิมพ์เป็นผลลัพธ์
Output

เพื่อป้องกัน floating point exceptions ใน C++ จำเป็นต้องตรวจสอบพารามิเตอร์ทั้งหมดที่ส่งให้ฟังก์ชัน ใช้รูปแบบที่เหมาะสม และทดสอบ divisors สำหรับค่าศูนย์อย่างชัดเจน นอกจากนี้ เมื่อใช้ double data types จำเป็นต้องขยายช่วงของ data type หากโปรแกรมต้องการผลลัพธ์คณิตศาสตร์ที่ใหญ่กว่า
สรุป
Floating point exceptions ใน C++ เกิดจาก invalid operations บนค่าตัวเลข และอาจส่งผลต่อความสามารถของโปรแกรมในการดำเนินการอย่างถูกต้อง เพื่อหลีกเลี่ยงข้อผิดพลาดเช่นนี้ จำเป็นต้องตรวจสอบพารามิเตอร์ทั้งหมดที่ส่งให้ฟังก์ชัน และใช้ data types ที่เหมาะสม นอกจากนี้ การจับ floating point exceptions ก็เป็นประโยชน์