C/C++浮点数使用的两个关键注意事项

Mason
Mason
发布时间:2026-10-15| 6人浏览过
原创

本文详细解析了C/C++中浮点数因精度问题导致的比较失效及大数加减异常现象,通过代码实例演示了使用eps阈值比较的正确方法,并附带分析了最大最小浮点数的内存分布规律。

浮点数存储原理与精度损失

C/C++中的浮点数(float和double)在计算机内存中遵循IEEE 754标准进行存储。这种存储方式将数值分为符号位、指数位和尾数位。由于二进制无法精确表示某些十进制小数(如0.1),在存入过程中可能会发生有效数值的截断或四舍五入,从而导致微小的精度损失。

正是因为这种底层机制,直接使用操作符(如 ==)比较两个理论上相等的浮点数,往往会得到不符合预期的结果。

注意事项一:不要直接比较浮点数是否相等

由于精度损失的存在,即使数学上相等的两个浮点数,在计算机内部也可能存在细微的差别。下面通过一个示例来验证这一点:

int main()
{
    float a = 3.12f;
    a += 0.02f;
   
    float b = 3.14f;
 
    std::cout << (a == b) << std::endl;
    std::cout << (a > b) << std::endl;
    std::cout << (a < b) << std::endl;
 
    return 0;
}

调试运行上述代码可以看到输出结果:



虽然从数学角度看,$3.12 + 0.02$ 应等于 $3.14$,但在实际运行中,由于精度丢失导致 $a < b$。如果业务逻辑依赖这种严格的相等判断,程序就会出错。

正确的做法是:判断两个浮点数的差值的绝对值是否小于一个允许的误差范围(EPS)。对于单精度浮点数,合适的精度通常为 1e-6;双精度浮点数则建议用 1e-16 左右。

可以定义如下宏来表示精度阈值:

#define epf 1e-6
#define epd 1e-16

判断逻辑如下:

  • 判断是否等于0: 需满足 $|x| \le EPS$。
    例如判断单精度浮点数 $f$ 是否为0:if(fabs(f) <= epf);
  • 判断两数是否相等: 需满足 $|x - y| \le EPS$。
    例如判断单精度 $f1$ 和 $f2$ 是否相等:if(fabs(f1 - f2) <= eps);

注:fabs 用于求浮点数的绝对值,需包含相应头文件(如 <iostream> 或 <cmath>)。

修正后的比较代码如下:

#define eps 1e-6
int main()
{
    float a = 3.12f;
    a +=0.02f;
    float b = 3.14f;
    if (fabs(a - b) <= eps)
    {
        std::cout << "a==b" << std::endl;
    }
    else
    {
        std::cout << "a!=b" << std::endl;
    }
    return 0;
}

执行该修正代码后,结果符合预期:



注意事项二:避免量级悬殊的浮点数运算

当两个绝对值相差巨大的浮点数进行加减运算时,结果往往没有意义。这是因为计算时需要统一阶码,较小数的尾数在进行位移时会超出精度范围而被舍去。

以十进制直观理解:

代码验证:

int main()
{
    float a = 1e38;
    std::cout << a << std::endl;
    
    float b = 1000;
    a = a + b; // 加上1000对1e38来说几乎没有影响
    std::cout << a << std::endl;
 
    a = a - b; 
    std::cout << a << std::endl;
    return 0;
}

运行结果如下,可以看出 $1e38$ 加上或减去 $1000$ 后值未变:

补充:观察 FLT_MAX 与 FLT_MIN

了解边界值在内存中的形式有助于深入理解浮点数限制。C/C++ 宏定义了浮点数的最大值(FLT_MAX)和接近0的最小值(FLT_MIN)。

观察 FLT_MAX:



将其二进制序列分割为符号(S)、指数(E)、尾数(M)形式来看:

可见其指数位并非全1。

观察 FLT_MIN:



同理,其指数位也非全0。

总结

在处理C/C++浮点数时,必须意识到其近似性的本质。为了避免逻辑错误,请养成使用 `fabs(diff) <= EPS` 进行比较的习惯,并避免在相差过大数量级的数字间进行加减。以上就是C/C++浮点数使用的两个注意事项的详细内容,更多关于C/C++浮点数注意事项的资料请关注本站其它相关文章!

相关标签:

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。