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

C 語言 double/printf 大數值異常:整數溢出後轉浮點

     編輯:程式設計綜合問答

現象

double a = 11111 * 11111;           // 1.23454e8  正確
double b = 111111111 * 111111111;   // -1.79e9  錯誤 (負數!)
double c = 11111111111 * 11111111111; // 更大錯誤

根因:整數字面量默認 int 型,乘法在 int 域內進行,溢出後再隱式轉 double

  • 11111 是 int (32位有符號,最大 2,147,483,647)。
    11111 * 11111 = 123,454,321 < 2.1e9 **未溢出**,正確轉為 double。
  • 111111111 是 int,**但乘積 12,345,678,987,654,321 遠超 int 範圍**,發生**有符號整數溢出** (未定義行為,通常環繞為負數),**然後**轉為 double 保留錯誤值。

修正:強制浮點字面量

double b = 111111111.0 * 111111111.0; // 或 111111111 * 111111111.0
// 更清晰:
double b = (double)111111111 * (double)111111111;

同理 int 打印異常

int x = 111111111 * 111111111; // 溢出,結果不可預期
printf("%d", x); // 打印負數或亂碼

**C 標準規定:有符號整數溢出屬於未定義行為 (UB)**,編譯器可任意優化,結果不可依賴。

最佳實踐

  1. **大整數字面量加後綴**:111111111L (long) 或 111111111LL (long long),或 111111111.0 (double)。
  2. **編譯器開啟溢出檢查**:GCC/Clang -fsanitize=undefined -ftrapv,MSVC /RTCc (運行時檢查)。
  3. **金融/精確計算用定點/十進制庫**,避免浮點誤差與整數溢出。

驗證代碼

#include 
#include 

int main() {
    printf("INT_MAX = %d\n", INT_MAX); // 2147483647
    long long correct = 111111111LL * 111111111LL;
    printf("Correct (long long) = %lld\n", correct); // 12345678987654321
    double b = 111111111.0 * 111111111.0;
    printf("Double correct = %.0f\n", b); // 12345678987654320.0 (浮點精度丟失最後位)
    return 0;
}
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved