两圆相切当且仅当圆心距平方等于半径和或差的平方;外切判为d²==(r₁+r₂)²,内切判为d²==(r₁−r₂)²,实际需用容差比较避免浮点误差。

判断两圆是否相切:核心是距离与半径关系
两个圆是否相切,只取决于圆心距离 d 与两半径 r1、r2 的数值关系。不需要求交点、不依赖浮点精度暴力迭代,直接用代数比较即可。
关键逻辑只有两条:
- 外切成立当且仅当
d == r1 + r2 - 内切成立当且仅当
d == abs(r1 - r2)(注意是绝对值,谁大谁小不影响)
这里 d 是圆心欧氏距离:sqrt((x1-x2)*(x1-x2) + (y1-y2)*(y1-y2))。但实际编码中应避免开方——直接比较平方距离更安全、更快。
用平方距离规避浮点误差和 sqrt 开销
直接比较 d == r1 + r2 在浮点下几乎必然失败。正确做法是:把等式两边平方,转为整数/浮点数的平方比较。
例如外切判断应写成:(x1-x2)*(x1-x2) + (y1-y2)*(y1-y2) == (r1 + r2)*(r1 + r2);内切则是:(x1-x2)*(x1-x2) + (y1-y2)*(y1-y2) == (r1 - r2)*(r1 - r2)(注意:这里 (r1 - r2)*(r1 - r2) 自动等于 abs(r1 - r2) 的平方,无需调用 abs)。
但现实中的浮点输入仍可能带来微小误差,所以必须引入容差(epsilon):
- 不要用
==,改用fabs(a - b) - 推荐
eps = 1e-9(对 double 足够,若坐标达 1e6 级别,可按比例放大 eps) - 平方距离本身也可能溢出,若坐标范围极大,先做差再平方前可考虑类型提升(如
long long)
区分内切与外切:顺序无关,但需排除退化情况
内切要求一圆在另一圆内部且仅接触一点,这意味着:小圆半径必须严格小于大圆半径,且圆心距等于半径差。但代码里不用 if 分大小——直接用 (r1 - r2)*(r1 - r2) 就覆盖了两种顺序。
真正要检查的退化情形有:
- 任一圆半径 ≤ 0:几何上无效,应提前返回 false 或抛异常
- 两圆同心(
d == 0)且r1 == r2:这是重合,不是内切;若r1 != r2,则无接触,更不是内切 - 计算前先判
d == 0,能避免后续误判内切(因为(r1-r2)^2可能巧合等于 0)
C++ 实操示例:一个健壮的 is_tangent 函数
bool is_tangent(double x1, double y1, double r1,
double x2, double y2, double r2) {
if (r1 double outer_sq = (r1 + r2) * (r1 + r2);
if (fabs(d_sq - outer_sq) <p>}</p>
这个函数返回 true 表示发生外切或内切(不区分是哪一种)。若需分别判断,可拆成两个函数或加输出参数。注意:它不处理 NaN 或无穷坐标,生产环境需前置校验。
最易被忽略的是容差尺度——eps 太小会漏判,太大可能把相交或分离误判为相切;务必根据你的坐标量级和精度需求调整。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











