用圆心距平方与半径和差平方比较可稳定判断两圆位置关系:完全分离当dist_sq>(r1+r2)²;外切当dist_sq==(r1+r2)²;相交当(r1−r2)²

怎么用圆心距判断两圆位置关系
直接看圆心距离和半径之和、半径之差的大小关系,这是最稳定、无浮点陷阱的判断方式。别依赖交点求解或向量投影——既慢又容易因精度出错。
设两圆为 c1(圆心 (x1, y1),半径 r1)和 c2(圆心 (x2, y2),半径 r2),先算平方距离避免开方:
double dx = x1 - x2; double dy = y1 - y2; double dist_sq = dx * dx + dy * dy;
再分类判断:
- 完全分离:当
dist_sq > (r1 + r2) * (r1 + r2)(注意是平方!) - 完全包含(
c1包含c2):当r1 >= r2且dist_sq - 完全包含(
c2包含c1):当r2 >= r1且dist_sq
为什么不能直接比较 sqrt(dist_sq) 和半径和/差
开方运算不仅慢,还会引入额外浮点误差,尤其在临界状态(比如两圆“刚好相切”)下容易误判。例如 sqrt(0.0001) 在某些平台可能略大于 0.01,导致本该判定为“外切”的情况被错归为“分离”。
更关键的是:所有几何判定都应尽量避开 sqrt,除非你明确需要方向向量。这里只关心大小关系,平方比较完全等价且更健壮。
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
注意:(r1 - r2) * (r1 - r2) 比 pow(r1 - r2, 2) 更快更安全,后者可能隐式转 double 再调库函数,还多一次函数调用开销。
边界情况怎么处理:相切、重合、半径为零
题目只要求“完全分离”或“完全包含”,所以相切(内切/外切)、相交、同心但半径相等(即重合)都不属于目标状态,必须排除。
- 外切时
dist_sq == (r1 + r2) * (r1 + r2)→ 不算“完全分离” - 内切时
dist_sq == (r1 - r2) * (r1 - r2)(且r1 != r2)→ 不算“完全包含” - 两圆重合(
dist_sq == 0且r1 == r2)→ 属于“完全包含”的退化情形,但按严格定义,此时互为包含;若业务要求排除,需额外判断dist_sq == 0 && r1 == r2 - 半径为零(点圆):只要把
r1或r2当作普通非负数参与计算即可,公式依然成立;但要注意r1 == 0 && r2 == 0时,仅当圆心重合才“完全包含”,否则“完全分离”
实际写成函数时容易漏掉的细节
很多人写成类似 bool isSeparate(Circle a, Circle b) 就完事,但没考虑浮点容差和参数顺序。真实场景中建议:
- 统一用
double计算,别混用float,尤其当坐标来自 OpenGL 或传感器数据时 - 加入小量容差(如
1e-9)处理计算误差,但仅用于等号判断(如是否相切),**不要**加在不等式里(比如dist_sq > (r1+r2)*(r1+r2) + eps是错的) - 若需同时判断多种关系,建议返回枚举而非多个 bool 函数,避免重复计算
dist_sq - 注意半径合法性:如果输入可能为负,先做
abs(r1)或断言,否则(r1 - r2) * (r1 - r2)仍正确,但语义已失真
最常被忽略的是:完全包含关系是非对称的,c1 包含 c2 和 c2 包含 c1 是两个独立条件,不能只检查一种。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










