NaN (Not a Number) เป็นค่าเฉพาะในระบบ Floating-Point (IEEE 754) ที่แทนผลลัพธ์ของการดำเนินการทางคณิตศาสตร์ที่ "ไม่ได้ถูกกำหนด" หรือ "ไม่สามารถแสดงเป็นตัวเลขได้" ใน C++ NaN เป็นส่วนหนึ่งของ float, double, และ long double
สถานการณ์ที่เกิด NaN
- รากที่สองของจำนวนลบ:
sqrt(-5) - การหารศูนย์ด้วยศูนย์:
0.0 / 0.0 - การดำเนินการกับ Infinity:
INF - INF,INF * 0 - ฟังก์ชันตรีโกณมีติกที่นอกโดเมน:
acos(2.0)
ตัวอย่างโค้ด
#include <iostream>
#include <cmath>
#include <limits>
using namespace std;
int main() {
double result = sqrt(-5.0);
cout << "Square root of -5: " << result << endl;
// Output: Square root of -5: nan
// ตรวจสอบ NaN
if (isnan(result)) {
cout << "Result is NaN!" << endl;
}
// สร้าง NaN โดยตรง
double nan_val = numeric_limits<double>::quiet_NaN();
cout << "Direct NaN: " << nan_val << endl;
// NaN ไม่เท่ากับตัวมันเอง (คุณสมบัติเฉพาะ)
cout << "NaN == NaN? " << (nan_val == nan_val) << endl; // false
return 0;
}
คุณสมบัติสำคัญของ NaN
- NaN != NaN - การเปรียบเทียบ NaN กับตัวเองจะคืนค่า
falseเสมอ - ใช้
std::isnan()(จาก<cmath>) เพื่อตรวจสอบแทนการเปรียบเทียบ - มีสองประเภท: Quiet NaN (แพร่กระจายโดยไม่ยก Exception) และ Signaling NaN (ยก Exception)
- การดำเนินการใดๆ กับ NaN จะให้ผลลัพธ์เป็น NaN ต่อไป (Propagation)
- ตรวจสอบ Input ก่อนเรียกฟังก์ชันคณิตศาสตร์ (เช่น
if (x >= 0) sqrt(x)) - ใช้
std::isnan()ตรวจสอบผลลัพธ์หลังการคำนวณที่อาจเกิด NaN - พิจารณาใช้
std::optionalหรือ Error Handling แทนการคืนค่า NaN ใน API
แนวทางปฏิบัติที่ดี (Best Practices)
สรุป
NaN เป็นกลไกมาตรฐานสำหรับจัดการข้อผิดพลาดทางคณิตศาสตร์ใน Floating-Point การเข้าใจพฤติกรรมของ NaN (โดยเฉพาะ NaN != NaN) จำเป็นสำหรับการเขียนโค้ดทางวิทยาศาสตร์/วิศวกรรมที่มั่นคงใน C++