python - 使用 Python math.acos() 时数值错误导致数学域错误

标签 python math

我使用 math.acos() 来计算两个向量之间的角度。思想是计算两个归一化向量的点积,并使用点积的arccos返回两个向量的角度(在0到pi的范围内)。

有时,两个向量在归一化后具有相同的方向,它们的点积应该为 1。但是,由于数值误差,它实际上是 0.999999999998,...或者有时是 1.0000000000002。后者以错误 ValueError: math domain error

杀死 math.acos()

我无意中发现了这个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/

相关文章:

python - 如何在本地针对 OAuth 进行开发?

swift - 计算按下两个按钮的百分比时为零

matlab - (MATLAB) 线性方程的所有整数正解

r - 如何挑选出矩阵中的特定值 [R]

c++ - 平面和射线相交的参数常数 t 的值?

python - 解析像 'ssh://git@gitlab.org.net:3333/org/repo.git' 这样的 git URL 吗?

Python Discord.py |邀请链接 on_ready 问题

python - Pyplot - 根据 y 轴值显示 x 轴标签

python - astropy.io.fits - HIERARCH 关键字不适用于 CONTINUE 卡 : Bug or "Feature" of the FITS standard?

image - 从点获取畸变变换