我使用 math.acos() 来计算两个向量之间的角度。思想是计算两个归一化向量的点积,并使用点积的arccos返回两个向量的角度(在0到pi的范围内)。
有时,两个向量在归一化后具有相同的方向,它们的点积应该为 1。但是,由于数值误差,它实际上是 0.999999999998,...或者有时是 1.0000000000002。后者以错误 ValueError: math domain error
我无意中发现了这个question询问类似的问题,但已关闭。在这里我重新提问,希望能更好地了解如何避免此类错误。
在我的例子中,我必须在进行点生成和 arccos 之前检查两个向量是否具有相同的方向。这有帮助,但我仍然想知道是否有更好的方法来做到这一点。
最佳答案
这是所有使用向量和浮点运算的人都会遇到的一个古老的数值问题。一个简单的修复方法是将计算角度的代码包装在一个具有一些钳制逻辑的函数中:
import numpy as np
import math
def angle_between(vhat1, vhat2, tol = 5e-6):
cosang = np.dot(vhat1, vhat2)
if math.fabs(cosang) > 1.0:
if math.fabs(cosang) - 1.0 < tol:
cosang = math.modf(cosang)[1]
else:
raise ValueError('Invalid arguments (vectors not normalized?)')
return math.acos(cosang)
w = np.array([ 1., 0., 0.])
z = np.array([-1., 0., 0.])
v = np.array([ math.sqrt(2.)/2., math.sqrt(2.)/2., 0.])
z1 = np.array([-1.0000001, 0., 0.])
w1 = np.array([9., 3., -5.])
print "{0:>5} deg".format(angle_between(v, w) * 180.0 / math.pi)
print "{0:>5} deg".format(angle_between(w, z) * 180.0 / math.pi)
print "{0:>5} deg".format(angle_between(w, z1) * 180.0 / math.pi)
# this last one will raise ValueError
print "{0:>5} deg".format(angle_between(w1, z1) * 180.0 / math.pi)
输出:
45.0 deg
180.0 deg
180.0 deg
...
ValueError: Invalid arguments (vectors not normalized?)
关于python - 使用 Python math.acos() 时数值错误导致数学域错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36672026/