做嵌入式开发那会儿,我写了个温度采集程序,结果发现明明传感器返回的是 36.6℃,程序里一比较却对不上。查了半天才发现,是 C++ 浮点精度在作怪。
浮点数不是精确存储的
C++ 中的 float 和 double 看着能存小数,其实底层是用二进制近似表示十进制小数。比如 0.1 这个数,二进制根本无法精确表达,就像 1/3 在十进制里是无限循环小数一样。
这就导致:
#include <iostream>
using namespace std;
int main() {
float a = 0.1f;
float b = 0.2f;
if (a + b == 0.3f) {
cout << "相等";
} else {
cout << "不相等"; // 实际输出这个
}
return 0;
}
这段代码输出“不相等”,因为 a + b 的结果其实是 0.3000001 左右,肉眼看不出来,但计算机比得可严了。
别直接用 == 比较浮点数
想判断两个浮点数是否“相等”,得引入一个极小的误差范围,也就是常说的 epsilon。
#include <iostream>
#include <cmath>
using namespace std;
const float EPSILON = 1e-6;
bool isEqual(float a, float b) {
return fabs(a - b) < EPSILON;
}
int main() {
float a = 0.1f + 0.2f;
float b = 0.3f;
if (isEqual(a, b)) {
cout << "可以认为相等";
}
return 0;
}
这样处理后,逻辑就稳了。EPSILON 通常取 1e-6 或 1e-7,具体看你的数据精度需求。
计算累计误差会放大
有次写金融计算模块,用 float 累加每天的利息,跑了几百天后结果差了几块钱。换成 double 才缓解。
建议:涉及钱、科学计算、大量迭代时,优先用 double。float 适合图形渲染这类对精度要求不高的场景。
打印时也得小心
用 cout 输出浮点数,默认只显示6位有效数字,可能掩盖真实问题。
#include <iomanip>
cout << fixed << setprecision(9) << a + b;
加上 setprecision 可以看清实际值,调试时很有用。
整数运算更可靠
如果业务允许,比如金额可以先乘100转成分来算,全程用整数,最后再除回去。这样彻底避开浮点坑。
像微信支付接口内部处理金额都是用分,不是元,就是这个道理。