Dev*_*per 2 python precision geometry numpy
我们使用以下代码计算两条线之间的锐角。
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))))
Run Code Online (Sandbox Code Playgroud)
它按预期工作。例如:
>>> AcuteAngle2([0,0,1,0],[0,0,0,1])
1.5707963267948966 #in rad = 90 degree
Run Code Online (Sandbox Code Playgroud)
但是我们最近发现它在某些特殊情况下会失败!
>>> AcuteAngle2([0,0,1,0],[0,0,1,0])
0.0
Run Code Online (Sandbox Code Playgroud)
这是正确的,但是:
>>> AcuteAngle2([0,0,1,1],[0,0,1,1])
2.1073424255447017e-08 #failed!
Run Code Online (Sandbox Code Playgroud)
这是不正确的!它应该是 0.0。
任何想法和解决方案?
更新 1:按照以下答案中的建议
使用Decimal包可能对某些情况有所帮助。然而,我们的问题仍未解决,因为 (1) 有很多代码需要大量时间来调整每个部分以使用Decimal. 此外,(2)性能显着下降。此外,在处理numpy数组时需要 (3) 大量更改。因此它对我们的情况没有用。我们正在考虑某种装饰器等,而不改变事物并保持numpy性能。顺便说一句,有些人可能会建议使用多精度包,例如 gmpy 等,请注意,它们需要在代码中进行大量调整,这对我们的情况没有帮助。
如果您关心准确性,则使用arccos锐角是一个坏主意。问题是,对于接近 0 的小角度变化,该角度的余弦几乎不会改变。因为arccos情况相反 - 对于余弦角的非常小的变化,变化更大。
在 2D 和 3D 中,更好的方法是使用 atan2(crossproduct.length,scalarproduct)
在 2D 中,这变为atan2( dx1*dy2-dx2*dy1 , dx1*dy1+dx2*dy2 ). 请注意,您不需要对向量进行归一化,因此有两个改进:
arccos