判斷 double/float 變數是否代表整數值(如 4.0、-3.0),不能直接用 n == (int)n 或 n - (int)n == 0,因浮點數表示誤差會導致誤判。正確做法是設定合理容差(epsilon)。
// 錯誤:浮點誤差導致 4.0 可能存為 3.999... 或 4.000...1
if (n - (int)n == 0) ...
bool isInteger(double n) {
const double EPS = 1e-15; // double 精度;float 用 1e-6
double diff = n - (long long)n; // 取小數部分
if (diff < 0) diff = -diff; // 絕對值
return diff < EPS || diff > 1.0 - EPS; // 接近 0 或接近 1 (如 -0.999...)
}
#include <cstdio>
#include <cmath>
bool isInteger(double n) {
const double EPS = 1e-15;
double diff = n - (long long)n;
if (diff < 0) diff = -diff;
return diff < EPS || diff > 1.0 - EPS;
}
int main() {
double n;
while (scanf("%lf", &n) == 1) {
puts(isInteger(n) ? "YES" : "NO");
}
return 0;
}
| 輸入 | 預期 | 實際 | 說明 |
|---|---|---|---|
| 0.000000000000001 (14零) | NO | NO | 超出 double 15 位有效數字 |
| 0.0000000000000001 (15零) | YES | YES | 實際存為 0.0 |
| 9.000000000000001 | NO | NO | |
| 9.0000000000000001 | YES | YES | 實際存為 9.0 |
long long 截斷整數部,避免 int 溢位。diff > 1 - EPS 處理 -0.999... 這類接近 -1 的負數小數部(如 -3.0 存為 -2.999...)。1e-15 針對 double(15-16 位有效數字);float 請用 1e-6。此法經實測可靠處理鍵盤輸入與計算產生的浮點數,是工程實踐的標準解法。