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

C 語言單精度浮點數 float 輸出精度問題:為何 11111.11111 變 11111.111328?

     編輯:C 語言問答

現象


float a = 11111.11111f;
double b = 11111.111111111111;
printf("%f\n%f\n", a, b);
// 輸出:
// 11111.111328
// 11111.111111

根本原因:二進制浮點數無法精確表示十進制小數

  • float (IEEE 754 binary32):**1 符號位 + 8 指數位 + 23 尾數位** ≈ **7-8 位十進制有效數字**。
  • 11111.11111 整數部份 5 位,僅剩 **2-3 位小數精度可靠**。
  • 十進制 0.11111 在二進制是**無限循環小數**,存入 float 時被捨入為最接近的二進制近似值。
  • 輸出時將此近似值轉回十進制,顯示為 11111.111328(實際儲存值最近似的十進制表示)。

為何書上說「有效位數 7 位,整數佔 5 位,小數剩 2 位」?

這是**經驗法則**:float 約 7.22 位十進制有效數字 (log10(2^24))。整數部份佔 5 位 → 小數可靠約 2 位。**實際可靠位數取決於具體數值大小**,非固定截斷。

正確處理浮點數輸出

  1. 指定輸出精度:printf("%.2f\n", a); → 11111.11(四捨五入顯示)。
  2. 金融/精確計算用整數/定點數:以「分」為單位存 long long,顯示時手動插入小數點。
  3. 科學計算用 double:15-16 位有效數字,誤差極小。
  4. 比較浮點數永不 ==:fabs(a-b) < 1e-6 (float) / 1e-12 (double)。

程式碼示範


#include 
#include 

int main(void) {
    float a = 11111.11111f;
    double b = 11111.111111111111;

    printf("預設 %%f (6位小數)      : a=%f  b=%f\n", a, b);
    printf("指定 %.2f (2位小數)       : a=%.2f b=%.2f\n", a, b);
    printf("指定 %.4f (4位小數)       : a=%.4f b=%.4f\n", a, b);
    printf("科學記號 %%e                : a=%e  b=%e\n", a, b);
    printf("十六進制浮點 %%a (精確位元) : a=%a  b=%a\n", a, b); // C99

    // 比較示範
    float x = 0.1f + 0.2f;
    float y = 0.3f;
    printf("0.1+0.2 == 0.3 ? %s (差值 %.2e)\n",
           fabsf(x - y) < 1e-6 ? "true" : "false", fabsf(x - y));
    return 0;
}

關鍵觀念總結

  • float 約 7 位十進制有效數字,**非小數點後 7 位**。
  • 輸出時**必須指定精度** (%.Nf),否則預設 6 位小數可能顯示雜訊。
  • **儲存 ≠ 顯示**:同一二進制值可用不同十進制字串表示(%f, %e, %a、%.Nf)。
  • 嚴謹場景**避免 float**,用 double 或定點數/十進制庫。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved