有关浮点数的“坑”

Aerhuo 发布于 25 天前 31 次阅读


浮点数是不精确的

计算机使用二进制存储数据,而很多十进制小数(如0.1)无法被有限的二进制小数精确表示,这导致了精度误差。因此,在编程中必须始终将浮点数视为近似值。

核心原则: 永远不要用 == 直接比较两个浮点数是否相等。


代码用例

用例1:经典的 0.1 + 0.2 != 0.3

#include <stdio.h>

int main() {
    float a = 0.1f;
    float b = 0.2f;
    float sum = a + b;
    float c = 0.3f;

    printf("0.1 + 0.2 的计算结果是: %.10f\n", sum);
    printf("0.3 本身是:            %.10f\n", c);

    if (sum == c) {
        printf("结果: 0.1 + 0.2 == 0.3\n");
    } else {
        printf("结果: 0.1 + 0.2 != 0.3\n");
    }

    return 0;
}

用例2:循环中的精度累积误差

#include <stdio.h>

int main() {
    float total = 0.0f;

    // 尝试将 0.1 加 10 次
    for (int i = 0; i < 10; i++) {
        total += 0.1f;
    }

    // 期望结果是 1.0,但实际上...
    printf("将 0.1 累加 10 次的结果是: %.10f\n", total);

    if (total == 1.0f) {
        printf("结果: total == 1.0\n");
    } else {
        printf("结果: total != 1.0\n");
    }

    return 0;
}

用例3:正确的浮点数比较方法

#include <stdio.h>
#include <math.h> // 需要引入 math.h 来使用 fabs()

int main() {
    double a = 0.1 + 0.2;
    double b = 0.3;
    const double EPSILON = 1e-9; // 定义一个极小的精度阈值

    printf("a 的值: %.17f\n", a);
    printf("b 的值: %.17f\n", b);

    // 错误的比较方法
    if (a == b) {
        printf("使用 == 比较: a 和 b 相等\n");
    } else {
        printf("使用 == 比较: a 和 b 不相等\n");
    }

    // 正确的比较方法
    if (fabs(a - b) < EPSILON) {
        printf("使用精度阈值比较: a 和 b 被认为是相等的\n");
    } else {
        printf("使用精度阈值比较: a 和 b 不相等\n");
    }

    return 0;
}