Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
python中计算两个向量夹角余弦的稳健方法是什么?_Python_Python 3.x_Numpy_Precision_Trigonometry - Fatal编程技术网

python中计算两个向量夹角余弦的稳健方法是什么?

python中计算两个向量夹角余弦的稳健方法是什么?,python,python-3.x,numpy,precision,trigonometry,Python,Python 3.x,Numpy,Precision,Trigonometry,我想计算Python中位于同一平面上的两个2D向量的夹角的余弦。我使用经典公式cosθ=v1∙v2/(| v1 | v2 |)。然而,根据我如何实现它,舍入误差可以为并行向量提供大于1或小于-1的值。实施的三个例子如下: import numpy as np def cos2Dvec_1(v1,v2): v1norm2 = v1[0]**2+v1[1]**2 v2norm2 = v2[0]**2+v2[1]**2 v1v2 = v1[0]*v2[0]+v1[1]*v2[

我想计算Python中位于同一平面上的两个2D向量的夹角的余弦。我使用经典公式cosθ=v1∙v2/(| v1 | v2 |)。然而,根据我如何实现它,舍入误差可以为并行向量提供大于1或小于-1的值。实施的三个例子如下:

import numpy as np

def cos2Dvec_1(v1,v2):
    v1norm2 = v1[0]**2+v1[1]**2
    v2norm2 = v2[0]**2+v2[1]**2
    v1v2 = v1[0]*v2[0]+v1[1]*v2[1]
    if v1v2 > 0:
        return np.sqrt(v1v2**2/(v1norm2*v2norm2))
    else:
        return -np.sqrt(v1v2**2/(v1norm2*v2norm2))

def cos2Dvec_2(v1,v2):
    r1 = np.linalg.norm(v1) 
    r2 = np.linalg.norm(v2)
    return np.dot(v1,v2)/(r1*r2)

def cos2Dvec_3(v1,v2):
    v1 = v1/np.linalg.norm(v1)
    v2 = v2/np.linalg.norm(v2)
    return np.dot(v1,v2)

v2 = np.array([2.0, 3.0])
v1 = -0.01 *v2
print(cos2Dvec_1(v2,v1), cos2Dvec_2(v1,v2), cos2Dvec_3(v1,v2))
当我在我的机器(Python 3.7.6、Numpy 1.18.1)上执行此代码时,我得到:

第二版和第三版之间的区别对我来说特别奇怪

如果我使用第二个函数通过反余弦计算角度,我将得到一个
nan
,我希望避免(我不想每次都检查,如果结果在[-1,1])。我想知道版本1和版本3(给出正确的结果)是否在所有情况下在数值上都是稳定的。

您可以使用确保值在-1和1之间被强制(或“钳制”或“钳制”)

return np.clip(YourOriginalResult, -1, 1)
操作浮动时,舍入误差是不可避免的。不幸的是,我对你的计算没有足够的专业知识来推荐你的任何方法


我建议您在添加
clip
部分以缓解那些“超出范围”的问题后,检查哪些具有正确的性能。

在计时
numpy.clip(x,-1,1)
之后,我发现一个更快的替代方法就是简单的老
y=max(-1,min(x,1))
。以下代码段的计时结果:

t1 = time.time()
vals = [-1.001, -0.99, 0.99, 1.001]
for ii in range(1):
    for x in vals:
        y = np.clip(x, -1, 1)
#       y = max(-1, min(x,1))
        print(y)
t2 = time.time()
print(t2-t1)

Numpy clip在我的笔记本电脑上的速度几乎慢了23倍。

你可以使用Numpy
clip
功能,它强制结果在特定范围内被“钳制”或“钳制”,谢谢你的建议。我想知道是否有一些结果得到保证的实现,而不诉诸结果后检查和操作。我的猜测是,为了避免运行时错误,这样的检查是不可避免的。在我的代码中,这不会太慢。是的,我相信numpy他们创建了一个优化的
np.clip
,我也同意,要分析复杂的计算来避免这些检查是很困难的。
t1 = time.time()
vals = [-1.001, -0.99, 0.99, 1.001]
for ii in range(1):
    for x in vals:
        y = np.clip(x, -1, 1)
#       y = max(-1, min(x,1))
        print(y)
t2 = time.time()
print(t2-t1)