不能用 std::abs(distance - r),因为 distance = sqrt(dxdx + dydy) 引入了额外浮点误差,且开方运算不可逆、精度损失不可控;直接比较 distance 与 r 还需再次计算 sqrt,违背“避免开方”的核心原则,增大误差累积风险。

用浮点数比较距离平方是否等于半径平方
直接判断点到圆心距离是否等于半径,在浮点运算下几乎总会失败。因为 sqrt 引入精度误差,且 == 对浮点数极不可靠。正确做法是避开开方,比较距离的平方与半径的平方,再引入容差(epsilon)处理浮点误差。
- 设圆心为
(cx, cy),半径为r,点为(x, y) - 计算
dx = x - cx,dy = y - cy,然后算dx * dx + dy * dy - 若该值与
r * r的差的绝对值小于1e-9(或根据坐标量级调整),认为点在边界上
为什么不能用 std::abs(distance - r)
因为 distance = std::sqrt(dx*dx + dy*dy) 本身就有两重误差:一是乘加过程的舍入,二是 sqrt 的近似实现。这两者叠加后,即使数学上严格相等,计算出的 distance 也可能偏差超过典型 eps(如 1e-9)。而距离平方只涉及基本算术,误差更小、更可控。
- 例如:当
dx=1.0,dy=1.0,r=sqrt(2),r*r在内存中本就无法精确表示,但dx*dx + dy*dy是精确的2.0 - 用
sqrt反而把问题复杂化,还多一次函数调用开销
边界判定的容差怎么选
容差不是固定写 1e-9 就行,它得和输入坐标的数量级匹配。若坐标是千米级(1e6),那么 dx*dx 可达 1e12,此时相对误差可能达 1e-12 * 1e12 = 1.0,容差设成 1e-9 就完全失效。
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
- 推荐用相对容差:比如
const double eps = 1e-9 * std::max({1.0, r*r, dx*dx, dy*dy}) - 更稳妥的做法是统一用
std::abs(sq_dist - r_sq) ::epsilon() * std::max(std::abs(sq_dist), std::abs(r_sq)) - 如果所有坐标都在 [-1000, 1000] 范围内,
1e-6通常足够;做图形拾取时甚至可放宽到1e-3(对应像素级容忍)
整数坐标场景可以完全避免浮点误差吗
可以,但仅限于判断「数学意义上是否恰好在边界上」——即是否满足 (x−cx)² + (y−cy)² == r²。前提是 cx、cy、x、y、r 全为整数,且平方结果不溢出 long long。
- 用
long long dx = x - cx;等,再算dx * dx + dy * dy == r * r - 注意:
r是整数半径,不是浮点数;若原始半径是小数(如2.5),就不能走这条路 - 溢出风险高:坐标 ±10⁵ 时,平方达 10¹⁰,
int肯定爆,必须用long long或int128(视编译器支持)
实际中最容易被忽略的是容差尺度和坐标范围的耦合——拿图形界面里鼠标坐标(像素级整数)的逻辑,直接套用到地理坐标系(经纬度带小数、值域大)上,会批量误判。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










