已知標準值 answer = 3.14159。輸入數值,若與標準值差的絕對值 ≤ 0.0001,輸出 "Close enough",否則輸出 "Not close enough"。
#include
#include // fabs()
int main() {
const double ANSWER = 3.14159;
const double EPS = 0.0001;
double input;
printf("請輸入一個數值: ");
if (scanf("%lf", &input) != 1) {
printf("輸入無效\n");
return 1;
}
double diff = fabs(input - ANSWER); // 絕對差值
if (diff <= EPS) {
printf("Close enough\n");
} else {
printf("Not close enough (差值: %.6f)\n", diff);
}
return 0;
}
| 輸入值 | input - ANSWER | fabs() | 判斷 |
|---|---|---|---|
| 3.14150 | -0.00009 | 0.00009 | ≤ 0.0001 ✓ |
| 3.14168 | +0.00009 | 0.00009 | ≤ 0.0001 ✓ |
| 3.14140 | -0.00019 | 0.00019 | > 0.0001 ✗ |
| 3.14178 | +0.00019 | 0.00019 | > 0.0001 ✗ |
不取絕對值會導致負差值永遠 ≤ 0.0001,邏輯錯誤。
int float_equal(double a, double b, double eps) {
double diff = fabs(a - b);
if (diff <= eps) return 1; // 絕對誤差足夠小
double max_abs = fabs(a) > fabs(b) ? fabs(a) : fabs(b);
return (diff / max_abs) <= eps; // 相對誤差足夠小
}
比較兩浮點數在 IEEE 754 表示中的整數差距,需位元操作或 nextafter。
// 錯誤示範
if (input == 3.14159) // 極可能失敗,因 3.14159 無法精確用二進制表示
// 正確
if (fabs(input - 3.14159) < 1e-9)
| 陷阱 | 後果 | 解決 |
|---|---|---|
用 abs() 而非 fabs() | abs() 接受 int,浮點數隱性轉型截斷小數,邏輯全錯 | 包含 <math.h>,用 fabs() |
| 未連結數學庫 | GCC 編譯報 undefined reference to 'fabs' | 編譯加 -lm:gcc test.c -o test -lm |
| EPS 設太大/太小 | 太大誤判、太小永遠不等 | 根據應用領域設定:科學計算 1e-9~1e-12、工程 1e-6、貨幣 0.005 |
| 忽略 NaN/Inf | 輸入非數字導致比較異常 | 先檢查 isnan()/isinf() |
#include
#include
int main() {
const double ANSWER = 3.14159;
const double EPS = 0.0001;
double input;
while (1) {
printf("請輸入數值 (輸入 0 結束): ");
if (scanf("%lf", &input) != 1) {
printf("輸入無效,清空緩衝區...\n");
while (getchar() != '\n'); // 清除錯誤輸入
continue;
}
if (input == 0) break;
if (fabs(input - ANSWER) <= EPS) {
printf("Close enough! 正確值約 3.14159\n");
break;
} else {
printf("Not close enough,差值: %.6f\n", fabs(input - ANSWER));
}
}
return 0;
}
fabs(a-b) <= eps 是標準模式fabs、sqrt、sin 等需連結數學庫scanf 回傳值檢查 + 緩衝區清理