C++ 擁有約 10 種整數類型與 3 種以上浮點類型,各自擁有不同的數值範圍、最大位數、精度等屬性。對金融、科學計算、圖形、數位訊號處理等領域,這些屬性至關重要。標準庫 <limits> 提供了系統化、可移植的方式在程式中查詢這些基本屬性。本文將示範如何善用 std::numeric_limits 獲取關鍵資訊。
浮點精度有限,硬體特性導致截斷與捨入。經典案例:
double d1 = 2., d2 = 3.;
d1 /= d2; // 2/3
if (d1 * 10 == (20. / d2)) // 條件本應為真,實則永不執行
do_equal();
兩邊結果分別為 6.6666666666666661 與 6.6666666666666670,微小差異導致判斷失敗。此即「數字噪音」,多數 Bug 根源。
epsilon())epsilon 為「大於 1 的最小可表示值與 1 之差」,代表該類型最小偏差極限。
#include <iostream>
#include <limits>
using namespace std;
cout << numeric_limits<double>::epsilon() << endl; // 輸出:2.22045e-016
==if ( ((d1 * 10) - (20.0 / d2)) <= numeric_limits<double>::epsilon() )
do_equal();
若差值不大於 epsilon,視為相等。若業務允許更大容忍度(如十億分之一),可自訂常數:
const double BILLIONTH = 1. / 1000000000;
if ( ((d1 * 10) - (20.0 / d2)) <= BILLIONTH )
// ...
記住:epsilon 是最小偏差極限,業務容忍度可更大,不可更小。
digits10 告訴你精度上限標準:在精度無損情況下能表示的最大十進制位數。
cout << numeric_limits<double>::digits10 << endl; // 15
cout << numeric_limits<long double>::digits10 << endl; // 18
cout << numeric_limits<long>::digits10 << endl; // 9(整數同樣適用)
若需 16 位十進制精度,double 不夠,long double 可滿足。
max() 與 min()cout << numeric_limits<int>::max() << endl; // 2147483647
整數類型 min() 返回最小值(負數);浮點類型 min() 返回最小正規化正數。若需浮點最小值(負),用 -max() 或 lowest()(C++11)。
非法運算產生的特殊編碼。分「安靜 NaN」(不發訊號)與「發訊號 NaN」。
double d = 0;
if (numeric_limits<double>::has_quiet_NaN)
d = numeric_limits<double>::quiet_NaN();
else if (numeric_limits<double>::has_signaling_NaN)
d = numeric_limits<double>::signaling_NaN();
else
cerr << "NaN for double isn't supported";
除以零等操作產生。
float f = 0;
if (numeric_limits<float>::has_infinity)
f = numeric_limits<float>::infinity();
else
cerr << "infinity for float isn't supported";
| 屬性 | 含義 | 範例 |
|---|---|---|
is_specialized | 是否為標準類型特化 | true |
is_signed | 是否有號 | true (int), false (unsigned) |
is_integer | 是否整數類型 | true (int), false (float) |
is_exact | 計算是否精確(無捨入) | true (int), false (float) |
radix | 基數(通常為 2) | 2 |
digits | 基數為基的位數(不含符號位) | 31 (32-bit int) |
digits10 | 十進制最大無損位數 | 15 (double) |
max_exponent10 | 最大十進制指數 | 308 (double) |
min_exponent10 | 最小十進制指數 | -307 (double) |
has_infinity | 是否支援無限大 | true |
has_quiet_NaN | 是否支援安靜 NaN | true |
has_signaling_NaN | 是否支援發訊號 NaN | true |
has_denorm | 是否支援非正規化數 | denorm_present |
is_iec559 | 是否符合 IEC 559(IEEE 754) | true |
numeric_limits<T>::max() 替代 INT_MAX 等巨集,增強可移植性與可讀性。==。digits10:根據業務精度需求選型,而非習慣性用 double。min()/max():自動化測試中驗證極值行為。is_iec559:確認目標平台浮點行為一致性。掌握 <limits> 庫,讓你的程式在數值邊界上游刃有餘,告別「在這個平台跑得好好的,換個編譯器就崩了」的噩夢。