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

C 語言 float 有效數字誤差:二進制浮點數表示原理與精度陷阱

     編輯:程式設計綜合問答

現象複現

輸入浮點數後輸出發現數值不一致,即使未超過 FLT_DIG (6~7 位) 宣稱的有效數字。測試代碼:

#include <stdio.h>
#include <float.h>
int main(void) {
    float test;
    char data[7];
    printf("Float has at least %d effective numbers\n", FLT_DIG);
    printf("Then i'm gonna check it!\n");
    printf("test data:_______\b\b\b\b\b\b\b");
    scanf("%f", &test);
    printf("please input again to confirm it:_______\b\b\b\b\b\b\b");
    scanf("%s", &data);
    printf("So %f is supposed to be %s", test, data);
    return 0;
}

根本原因

十進制小數無法精確轉換為二進制浮點數。IEEE 754 單精度(float)結構:

  • 1 位符號位
  • 8 位指數位
  • 23 位尾數位(隱含 1 位,實際 24 位精度)

十進制 0.1、0.2 等常見數值在二進制中為無限循環小數,截斷後產生誤差。例如:

float x = 0.51f; // 二進制無法精確表示
float y = 0.5f;  // 二進制精確表示為 0.1
printf("x=%.8f y=%.8f", x, y); // 輸出 0.50999999 0.50000000

有效數字的真實含義

FLT_DIG = 6 表示:任意 6 位有效十進制數字轉為 float 再轉回十進制,能保證原值不變。但單個數值的轉換誤差可能導致第 7 位發生變化,且累積運算會放大誤差。

解決策略

  1. 顯示格式化:使用 printf("%.2f", val) 限制輸出位數,掩蓋尾部噪聲。
  2. 使用 double:雙精度(53 位尾數)誤差極小,滿足大多數業務需求。
  3. 定點數/整數運算:金融計算建議用長整型存儲分/厘,避免浮點誤差。
  4. 專用庫:如 decNumber、Java BigDecimal 實現十進制精確運算。

進階認知

浮點運算本質上是近似計算。理解「機器數」與「真值」的差異,掌握誤差分析方法(絕對誤差、相對誤差、機器 epsilon),才能編寫健壯的數值計算程序。

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