前言:浮點數不是「近似值」,是「編碼規範」
C 語言 `float`(單精度,32 位)與 `double`(雙精度,64 位)嚴格遵循 **IEEE 754** 標準(舊稱 IEEE R32.24 / R64.53)。理解其位級佈局,是掌握精度損失、特殊值(NaN/Inf)、類型轉換行為的鑰匙。
位域結構對比
| 字段 | float (32-bit) | double (64-bit) |
| 符號位 (Sign) | 1 bit (bit 31) | 1 bit (bit 63) |
| 指數位 | 8 bits (bit 30-23) | 11 bits (bit 62-52) |
| 尾數/有效位 | 23 bits (bit 22-0) | 52 bits (bit 51-0) |
| 偏移量 | 127 | 1023 |
數值解碼公式
Value = (-1)^Sign × 1.Mantissa × 2^(Exponent - Bias)
- **規格化數**:指數位不全 0/全 1。隱含前導 1(`1.M`)。
- **非規格化數**:指數位全 0。無隱含 1(`0.M`),指數固定為 `1-Bias`,表示極小值漸進下溢。
- **特殊值**:指數位全 1。尾數 0 → ±Infinity;尾數非 0 → NaN。
實例:`float f = 2.25f` 的內存佈局
- 二進制:`2.25 = 10.01₂ = 1.001₂ × 2¹`
- 符號位:`0`(正數)
- 指數:`1 + 127 = 128 = 10000000₂`
- 尾數:`001` + 20 個 0 → `00100000000000000000000`
- 完整 32 位:`0 10000000 00100000000000000000000` = `0x40100000`
工程啟示
- 精度邊界:`float` 約 7 位十進制有效數字,`double` 約 15 位。超出即丟失精度。
- 比較陷阱:絕不直接 `==` 比較浮點數,使用 `fabs(a-b) < epsilon`。
- 類型懲罰:`float` 參與運算常隱式提升為 `double`,存回又截斷,產生雙重誤差。
- 位操作調試:用 `union { float f; uint32_t u; }` 直接檢視位模式,定位 NaN/Inf 來源。
掌握 IEEE 754,讓浮點數從「不可控的黑盒」變為「可預測的工程工具」。