浮点数在C++中用二进制近似表示十进制小数,存在固有误差;0.1和0.2在二进制中为无限循环小数,无法精确存储,导致0.1+0.2≠0.3;应使用误差范围abs(a-b)

浮点数在C++中不是精确表示小数的工具,而是用二进制近似存储十进制小数,因此几乎所有小数运算都存在固有误差。这不是bug,而是IEEE 754标准下的正常现象。
为什么0.1 + 0.2 != 0.3?
十进制小数0.1在二进制中是无限循环小数(类似十进制里的1/3 = 0.333…),无法用有限位数精确表示。float通常只有约7位有效数字,double约15–17位,超出部分被截断或舍入,导致计算结果偏差。
- 例如:0.1f + 0.2f 实际得到的是0.30000001192092896(float精度下)
- 0.1 + 0.2 == 0.3 判断几乎总是false
如何安全地比较浮点数?
不用==直接比较,改用“是否落在某个误差范围内”:
- 定义一个极小值eps,比如1e-6(float)或1e-9(double)
- 写成:abs(a - b)
- 更稳妥的做法是用相对误差:abs(a - b) ,避免大数或接近零时失效
哪些操作会放大误差?
误差会在多次运算中累积或放大:
立即学习“C++免费学习笔记(深入)”;
- 大量加减小数值(如累加1e-6重复100万次)
- 相近大数相减(如1000000.0000001 - 1000000.0,有效位大幅损失)
- 用float做中间计算再转double——精度已在float阶段丢失,提升类型无用
什么情况下该换方案?
如果业务要求精确小数行为(如金融计算、配置解析、测试断言),别硬扛浮点误差:
- 用整数代替:金额存“分”而非“元”,比例用万分比(1234代表12.34%)
- 用字符串或专用库:如boost::multiprecision::cpp_dec_float或decimal类(C++23正在标准化)
- 输入时就转整数:std::stof("0.1")仍是近似值,不如解析字符串后按小数位乘10^n转整型
基本上就这些。理解浮点数是“近似容器”而非“小数计算器”,很多奇怪结果就变得合理了。









