浮点误差下“精确位于弧线上”不可行,需用容差判断距离是否接近半径、角度是否在指定区间内,并处理退化情况。

浮点误差导致的“精确位于”根本不存在
在 C++ 里,用 double 或 float 表示坐标和半径时,“精确位于周界弧线上”这个说法本身是病态的——浮点数无法精确表示大多数实数(比如 √2、π 或任意非整数距离),更不可能靠 == 判断一个计算出的距离是否“刚好等于”半径。
真正能做的,是判断点是否落在「以半径为基准、允许微小误差的环形带内」,同时还要确认该点是否落在你指定的那段弧线角度范围内。
- 直接比较
distance == radius几乎总是false,哪怕数学上成立 - 必须引入容差(tolerance),典型值如
1e-9(对double)或1e-5(对float) - 容差大小取决于坐标量级:若坐标在百万级,
1e-9可能太小;若在 0.001 级,又可能太大
用 std::hypot 计算距离并做容差比较
别手写 sqrt(dx*dx + dy*dy) —— 它容易溢出或下溢;std::hypot(dx, dy) 是标准库提供的稳健替代方案,专为避免中间结果溢出设计。
假设圆心为 (cx, cy),待测点为 (x, y),半径为 r:
double dx = x - cx; double dy = y - cy; double dist = std::hypot(dx, dy); bool on_circle = std::abs(dist - r)
-
tolerance不是固定常量,建议设为std::max(1e-9, r * 1e-12)这类相对+绝对混合容差 - 如果
r是 0,需单独处理(退化为点圆,此时只有x==cx && y==cy才成立) - 注意
std::hypot在 C++11 起可用;若编译器老旧,可用boost::math::hypot替代
判断是否落在指定弧线角度区间内
仅满足距离条件还不够——你得确认该点对应的角度在目标弧线范围内(例如从 30° 到 120° 的逆时针弧)。C++ 中用 std::atan2(dy, dx) 获取 [-π, π] 区间的弧度角,再归一化到 [0, 2π) 更便于区间比较。
double angle = std::atan2(dy, dx); if (angle
- 弧线通常由起始角
start_angle和终止角end_angle(单位:弧度)定义,注意区分顺/逆时针方向 - 若为逆时针弧,且
start_angle ,则检查 <code>angle >= start_angle && angle - 若
start_angle > end_angle(跨 0° 的弧,如 300°→60°),需拆成两段:angle >= start_angle || angle - 角度比较也需容差,尤其当
angle接近边界时,避免因浮点舍入误判
完整逻辑不能省略的三个检查点
一个可靠的“是否在弧线上”判断,必须串联以下三步,缺一不可:
- 先验证点到圆心距离是否在容差内(
on_circle) - 再计算该点角度,并归一化到 [0, 2π)
- 最后按弧线方向与区间规则,判断角度是否落入有效范围(注意端点是否包含)
最容易被忽略的是:当弧线是闭合的(比如整圆),有人会漏掉角度归一化或跨零判断;当点恰好是圆心(dx=dy=0),atan2(0,0) 返回 0,但此时它不在任何非退化弧线上——得提前拦截。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











