不能直接用==比较浮点数、字符串(java/c)、字典/集合、自定义类型等,因==比较地址或存在精度误差/无序性/未重载__eq__,易致typeerror、误判或npe。

为什么不能直接用 == 或 比较浮点数
因为浮点数在内存中是二进制近似表示,很多十进制小数(比如 0.1)无法精确存储。直接比较会导致本该相等的数被判为不等,或大小关系颠倒。例如:0.1 + 0.2 == 0.3 在 C++ 中通常返回 false。
用相对误差 + 绝对误差判断是否“足够接近”
工业级做法是定义一个容差(epsilon),但不能只用固定 1e-9 这类绝对值——当数值很大(如 1e20)时,这个 epsilon 完全没意义;数值很小时(如 1e-20),又可能误判。正确方式是结合相对和绝对容差:
bool float_equal(double a, double b, double abs_eps = 1e-9, double rel_eps = 1e-6) {
double diff = std::abs(a - b);
if (diff
-
abs_eps应对接近零的数(避免除零和相对误差失效) -
rel_eps控制数量级上的相对精度,一般取1e-6(对应float)或1e-12(对应double) - 不要用
std::numeric_limits<double>::epsilon()</double>直接当比较阈值——它表示的是1.0附近的最小可分辨差,不是通用容差
比较大小(a )时怎么加精度保护
直接写 a 仍会出错。稳妥做法是先判断是否“基本相等”,再决定大小关系:
int float_compare(double a, double b) {
if (float_equal(a, b)) return 0;
return a
- 返回
0、-1、1更利于集成到std::sort或自定义比较器中 - 若只关心严格小于(比如做边界判断),可改用
a ,但要注意:减去容差后可能让原本 <code>a == b的情况被误判为a - 涉及排序或查找时,比较函数必须满足**严格弱序**,否则
std::sort行为未定义——这意味着float_compare(a,b)==0必须对称且可传递
实际项目里建议用现成工具而不是手写
重复造轮子容易漏掉边界情况(如 NaN、Inf)。推荐方案:
- 用
boost::math::fpc::close_at_tolerance(需引入 Boost.Math) - C++23 引入了
std::isgreaterequal等函数,但它们仍不处理精度,仅规避 NaN 导致的异常 - 自己封装时务必测试
NaN输入——std::abs(NAN)是NAN,参与比较会传播,应提前用std::isnan()拦截
最常被忽略的是:精度比较不是纯数学问题,它取决于你的业务语义——是“物理测量误差允许范围”,还是“计算迭代收敛阈值”?选错 rel_eps 可能掩盖算法缺陷,而不是解决浮点问题。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











