float sum = 0;
for (int i = 0; i < 100; i++) sum += 0.1f;
printf("%f\n", sum); // 輸出 10.000002
程式邏輯無誤,結果卻偏離預期。根因在於二進制無法精確表示十進位 0.1。
十進位小數轉二進制:乘 2 取整數部分。
0.1 × 2 = 0.2 → 0
0.2 × 2 = 0.4 → 0
0.4 × 2 = 0.8 → 0
0.8 × 2 = 1.6 → 1
0.6 × 2 = 1.2 → 1
0.2 × 2 = 0.4 → 0 ... 循環
結果:0.1₁₀ = 0.0001100110011...₂(1100 無限循環)。
| 欄位 | 位數 | 說明 |
|---|---|---|
| 符號位 | 1 | 0=正,1=負 |
| 指數位 | 8 | Excess-127 編碼(實際指數 = 儲存值 - 127) |
| 尾數位 | 23 | 隱含首位 1,實際精度 24 位 |
儲存值 = (-1)^符號 × 1.尾數 × 2^(指數-127)
0.75₁₀ = 0.11₂ = 1.1 × 2^(-1) 符號=0, 指數=126(01111110), 尾數=1000...0 記憶體:0 01111110 10000000000000000000000
1100。1.49e-9)。~2e-6,顯示為 10.000002。double 尾數 52 位,誤差 ~1e-16,100 次累加誤差 ~1e-14,通常列印為 10.000000000000002。依然不精確。
int64_t,運算全程整數,顯示時除 100 插入小數點。libfixmath、decNumber 等專用庫。if (fabs(a - b) < EPS) ... 而非 a == b。EPS 視量級設定(如 1e-9)。浮點數是近似值而非精確值。理解 IEEE 754 編碼、二進制循環小數本質、誤差累積機制,並在涉及金融、科學計算時採用整數化或專用庫,是每位 C/C++ 開發者的必修課。