浮点数不能直接用==判断点是否在圆上,因计算存在精度误差,正确做法是引入容差epsilon进行近似比较,如abs(dist_sq - r_sq)
浮点数比较不能直接用 == 判断点在圆上
因为
double或float计算存在精度误差,哪怕数学上严格满足(x−cx)²+(y−cy)² == r²,实际计算结果大概率不等于r*r。直接写dist_sq == r_sq几乎总会返回false,哪怕点肉眼看起来“正好”在圆上。正确做法是引入容差(epsilon)做近似比较:
const double EPS = 1e-9; double dx = x - cx; double dy = y - cy; double dist_sq = dx * dx + dy * dy; double r_sq = r * r; bool on_circle = std::abs(dist_sq - r_sq) <h3>选多大的 epsilon 取决于坐标量级和精度需求</h3><p>固定 <code>EPS = 1e-9</code> 在大多数二维几何场景下够用,但若坐标值很大(比如 <code>cx</code> 达到 <code>1e6</code>),<code>dx*dx</code> 可能损失有效位数,此时相对误差比绝对误差更可靠:</p>
- 用
std::abs(dist_sq - r_sq)- 或者更稳妥:用
std::abs(std::sqrt(dist_sq) - r) (但开方有性能开销)- 若所有输入都是整数且半径平方可精确表示,可改用整数运算避免浮点误差
整数坐标 + 整数半径时可用完全精确判断
当
cx,cy,x,y,r全为整数,且你关心的是“数学意义上是否恰好在周界”,就该用整数运算:long long dx = (long long)x - cx; // 防溢出,用 long long long long dy = (long long)y - cy; long long dist_sq = dx * dx + dy * dy; long long r_sq = (long long)r * r; bool on_circle = dist_sq == r_sq;注意点:
- 必须保证乘法不溢出,否则结果未定义 —— 用
long long是底线,必要时上__int128或大数库- 如果输入含负数,
dx*dx仍安全;但若r是负数,需先取绝对值再平方- 此方法零误差,但仅限整数输入场景;一旦出现小数坐标,立刻退回到浮点容差方案
别忽略坐标系与单位一致性
常见翻车点不是算法,而是单位混用:
r是像素单位,但x,cx是归一化设备坐标(范围 [-1,1])→ 数值量级差几个数量级,EPS必须重调- 使用 OpenGL 或 Vulkan 的 NDC 坐标时,圆心可能被投影变换扭曲,此时“圆”在屏幕空间已变成椭圆,
on_circle判定失去几何意义- 若点由插值生成(如 fragment shader 中的
gl_FragCoord),需确认其是否对齐像素中心(通常 x=0.5, y=0.5 起始),否则理论上的“精确”点可能根本不存在于采样位置真正麻烦的从来不是公式怎么写,而是你手里的
x、y、r到底代表什么,以及它们在哪个空间里被定义。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!












