首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

C 語言浮點數深度解析:定點 vs 浮點、IEEE 754 表示法與精度陷阱

     編輯:程式設計綜合問答

什麼是浮點數?為什麼 0.1 + 0.2 != 0.3?本文從定點數與浮點數的本質差異切入,詳細解析 IEEE 754 標準下的儲存結構、指數偏移、尾數隱含位,並說明精度誤差產生的根本原因與應對策略。

定點數:固定小數點位置的整數偽裝

定點數約定小數點固定在第 N 位,例如第 3 位:

123.456 → 儲存為整數 123456,運算時除以 1000
0.00123456 → 只能表示為 0.001(截斷誤差)

優點:運算速度快(整數運算)、無精度誤差(在範圍內)。
缺點:動態範圍極小,無法同時表示極大與極小數值。

浮點數:科學記號法的二進制實現

浮點數採用「科學記號法」:

值 = (-1)^符號 × 1.尾數 × 2^(指數-偏移量)

以 32 位元 float 為例(IEEE 754 Single Precision):

欄位位數說明
符號位1 bit0=正,1=負
指數位8 bits移碼表示,偏移量 127
尾數位23 bits隱含首位 1,實際精度 24 bits

實際編碼範例

  • -0.0012345 → 科學記號:-1.2345 × 10^-3 → 二進制近似編碼
  • 1234500000 → 科學記號:1.2345 × 10^9 → 指數大、尾數相同

關鍵權衡:指數位越多 → 範圍越大;尾數位越多 → 精度越高。雙精度 double 為 1+11+52 位元,大幅擴展兩者。

為什麼會有精度誤差?

許多十進制小數(如 0.1、0.2)在二進制下是無限循環小數:

0.1₁₀ = 0.0001100110011...₂ (無限循環)
0.2₁₀ = 0.001100110011...₂ (無限循環)

尾數只有 23/52 位,必須捨入,導致 0.1 + 0.2 = 0.30000000000000004。

工程應對策略

  1. 金融/貨幣計算:使用整數分/厘單位,或 BigDecimal / 定點數庫。
  2. 比較浮點數:Math.abs(a - b) < EPSILON,而非 a == b。
  3. 輸出格式化:printf("%.2f", val) 避免顯示多餘尾數。
  4. 關鍵路徑用 double:除非記憶體/頻寬極其受限,預設用 double(52 位尾數)降低累積誤差。

總結

浮點數是「用有限位元逼近無限實數」的工程妥協。理解其儲存結構與誤差來源,是寫出健壯數值程式的前提。下次看到 0.1 + 0.2 != 0.3,請告訴自己:這不是 Bug,是 IEEE 754 規範下的必然結果。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved