Python:计算锐角的精度失败

标签 python numpy geometry precision

我们使用以下代码计算两条线之间的锐角。

def AcuteAngle2(line1,line2):
   ''':: line(x1,y1,x2,y2)'''
   u = (line1[2]-line1[0], line1[3]-line1[1])
   v = (line2[2]-line2[0], line2[3]-line2[1])
   return arccos(abs(dot(u,v)/(norm(u)*norm(v))))

它按预期工作。例如:

>>> AcuteAngle2([0,0,1,0],[0,0,0,1])
1.5707963267948966         #in rad = 90 degree

但是我们最近发现它在某些特殊情况下会失败!

>>> AcuteAngle2([0,0,1,0],[0,0,1,0])
0.0

这是正确的,但是:

>>> AcuteAngle2([0,0,1,1],[0,0,1,1])
2.1073424255447017e-08                #failed!

这是不正确的!它应该是 0.0。
有什么想法和解决方案吗?

更新 1:
按照以下答案中的建议使用 Decimal 包可能对某些情况有所帮助。然而,我们的问题仍未解决,因为 (1) 有很多代码需要大量时间来调整每个部分以使用 Decimal。此外,(2)性能显着下降。此外,它需要 (3) 在处理 numpy 数组时进行大量更改。因此它对我们的案例没有用。我们正在考虑某种装饰器等,而不改变任何东西,同时保持 numpy 的性能。顺便说一句,有些人可能会建议使用 gmpy 等多精度包,请注意它们需要在代码中进行大量调整,这对我们的情况没有帮助。

最佳答案

如果您关心准确性,则对锐角使用 arccos 不是一个好主意。问题在于,对于接近 0 的角度的微小变化,该角度的余弦几乎不会改变。对于 arccos,情况正好相反 - 对于余弦角变化非常非常小的变化。

在 2D 和 3D 中,更好的方法是使用 atan2(crossproduct.length,scalarproduct)

在 2D 中,这变为 atan2( dx1*dy2-dx2*dy1 , dx1*dy1+dx2*dy2 )。请注意,您不需要规范化向量,因此有两个改进:

  • arccos 没有错误放大
  • 没有平方根的额外误差

关于Python:计算锐角的精度失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16966325/

相关文章:

python - 使用 Flask/Postgres 安装 psycopg2

python - 在图例、matplotlib、Python 中使用代理艺术家

python - 如何解决 KeyError(f"None of [{key}] are in the [{axis_name}]") 在这种情况下(Pandas)?

python - 数据立方体的高斯卷积

python - 使用 alembic 创建数据库表和在 SQLAlchemy 中定义模型有什么区别?

python - 如何使用 numpy 有效地对矩阵的左上角求和?

python - 如何在 python matplotlib 中将 Z 轴映射到 3D 图形上

javascript - JS Canvas - 以指定 Angular 画线

mysql - MySQL 的 Haversine 公式的逆向?

graphics - 如何测试线段是否与二维轴对齐矩形相交?