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

C語言fmod函數浮點數餘數判斷陷阱與正確做法

     編輯:程式設計綜合問答

使用C語言fmod函數計算浮點數餘數時,直接用== 0判斷是否整除往往失效。本文解析浮點數存儲誤差導致的問題,並給出正確的判斷方法。

問題代碼

float x = 1 + (80.1 - 76) / (76 - 75);  // x = 5.1
for (y = 380; y <= 450; y++)
    if ((n = fmod(y, x)) == 0)  // 預期 y=408 時 n=0
        { m = y; break; }

理論上 408 ÷ 5.1 = 80 餘 0,但程序無法檢測到。

根本原因:浮點數精度誤差

  • 5.1 在二進制中無法精確表示,存儲為近似值
  • fmod(408, 5.1) 計算結果非精確 0,而是極小值如 1.13687e-13
  • == 0 比較失敗

正確判斷方法:絕對值比較

#include <math.h>  // 需引入 fabs

if (fabs(fmod(y, x)) < 0.0001)  // 設定容差閾值
    { m = y; break; }

閾值選擇原則

  • 根據數據量級設置,如 1e-6、1e-9
  • 通用宏定義:#define EPS 1e-9
  • 判斷相等:fabs(a - b) < EPS
  • 判斷為零:fabs(x) < EPS

完整修正代碼

#include <stdio.h>
#include <math.h>

#define EPS 1e-9

int main() {
    int a, b, m, y;
    float x, n;
    
    x = 1 + (80.1 - 76) / (76 - 75);  // 5.1
    
    for (y = 380; y <= 450; y++) {
        n = fmod(y, x);
        if (fabs(n) < EPS) {  // 正確判斷
            m = y;
            break;
        }
    }
    
    for (a = 0; a <= m; a++) {
        b = m - a;
        if (fabs(75*a + 80.1*b - (a+b)*76) < EPS)  // 同理修正
            printf("男生:%d, 女生:%d\n", a, b);
    }
    return 0;
}

延伸:浮點數比較最佳實踐

  1. 絕不使用 == 或 != 直接比較浮點數
  2. 定義 EPS 作為容差常量
  3. 大數值比較時考慮相對誤差:fabs(a-b)/fmax(fabs(a),fabs(b)) < EPS
  4. 財務/金融計算建議用整數(分為單位)或定點數庫

總結

fmod 本身正確,問題在於浮點數比較方式。牢記「浮點數判等必用容差」原則,可避免 90% 的數值計算 Bug。

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