浮点数比较应避免直接用“==”判断,而需引入与输入量级匹配的容差epsilon:对小量级用较小epsilon,大量级用较大epsilon,优先采用相对误差;nan或无穷大坐标会导致dist_sq为nan,使比较恒为false;图形库可能自带像素级容差,额外容差易引发不一致;epsilon本质是数值稳定性与效率的折中。

浮点数比较导致的“精确”陷阱
直接用 distance == radius 判断点是否在圆周上几乎总会失败——因为浮点运算存在舍入误差,哪怕数学上严格相等,计算出的距离平方与 radius * radius 也大概率不完全相等。
真正可行的做法是判断两点间距离平方与半径平方的差值是否落在一个极小容忍范围内(epsilon)。这个 epsilon 不能拍脑袋定,得和输入量级匹配:
- 若坐标和半径都在
1e-6量级,用1e-12做容差可能太松; - 若坐标达
1e6,用1e-9可能太紧,反而漏判; - 更稳妥的是用相对误差:
abs(dist_sq - r_sq) ; - 或者直接对距离做比较(避免开方):
abs(sqrt(dist_sq) - radius) ,但 sqrt 有额外开销且不必要。
推荐写法:只算距离平方 + 合理 epsilon
避免开方、减少误差源、兼顾效率。假设圆心 center,点 p,半径 r:
double dx = p.x - center.x; double dy = p.y - center.y; double dist_sq = dx * dx + dy * dy; double r_sq = r * r; double eps = 1e-9; // 对多数 <code>double</code> 场景够用,但需按数据尺度调整 if (std::abs(dist_sq - r_sq) <p>注意:<code>std::abs</code> 对 <code>double</code> 是安全的;若用 <code>float</code>,建议改用 <code>std::fabs</code> 或统一用 <code>double</code> 计算;<code>eps</code> 不要设成 <code>0</code>,也不要用 <code>DBL_EPSILON</code> 直接当容差——它描述的是 1.0 附近的最小可表示差,不是通用阈值。</p><div class="aritcle_card flexRow artxards"> <div class="artcardd flexRow"> <a class="aritcle_card_img" rel="nofollow" href="/xiazai/gongju/2823" title="C++14"><img src="https://img.php.cn/upload/manual/001/431/639/6ac8b33c327c4749.png" alt="C++14" onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a> <div class="aritcle_card_info flexColumn"> <a rel="nofollow" href="/xiazai/gongju/2823" title="C++14" class="overflowclass">C++14</a> <p class="overflowclass">C++14 对 C++11 的修正与增强版本,适合旧系统维护和较老工具链兼容。</p> </div> <a rel="nofollow" href="/xiazai/gongju/2823" title="C++14" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span> </a> </div> </div><h3>整数坐标下的“真精确”判断</h3><p>如果所有输入(圆心、点、半径)都是整数,且你追求数学意义上的“精确位于”,那么可以绕过浮点、全程用整数运算:</p>
- 检查
(p.x - cx)*(p.x - cx) + (p.y - cy)*(p.y - cy) == r*r是否成立; - 前提是乘积不会溢出 —— 若坐标范围大(如 > 1e5),
int可能溢出,应升级为long long; - 半径必须是整数,否则“精确位于”本身在整数坐标系下无定义(比如半径
sqrt(2)的圆过整数点(1,1),但r*r == 2仍可整数判断)。
实际应用中容易忽略的边界情况
很多实现只考虑几何逻辑,却栽在工程细节上:
- 半径为负时,
r*r仍是正数,但语义非法——应先校验r >= 0; - 圆心或点坐标是
NaN或无穷大,dist_sq会变成NaN,任何比较都返回false,且不报错; - 使用
float时,1e-5f容差比1e-9更合理,但也要看坐标范围; - 某些图形库(如 OpenGL 裁剪、SVG 渲染)对“圆周上”的判定可能自带像素级 tolerance,代码里再套一层容差反而引发不一致。
所谓“精确”,从来不是数学等号,而是你愿意为数值稳定性和运行效率折中的那个 epsilon 值。选错了,要么全判错,要么全判对。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










