Каков надежный метод вычисления косинуса угла двух векторов в python? - PullRequest
2 голосов
/ 03 августа 2020

Я хочу вычислить косинус угла двух 2D-векторов, которые l ie на одной плоскости в Python. Я использую формулу classi c 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), я получаю:

-1.0 -1.0000000000000002 -1.0

Разница между 2-й и 3-й версиями функции для меня особенно странная ...

Если я использую вторую функцию для вычисления угла через обратный косинус, я получу nan, чего я хочу избежать (и не хочу каждый раз проверять, лежит ли результат в [-1,1]). Однако мне было интересно, стабильны ли версии 1 и 3 (которые дают правильный результат) во всех случаях численно.

1 Ответ

1 голос
/ 03 августа 2020

Вы можете использовать clip функцию , чтобы гарантировать, что значения будут принудительно (или «зажаты», или «отсечены») между -1 и 1.

return np.clip(YourOriginalResult, -1, 1)

Ошибки округления неизбежны при манипулировании поплавками. К сожалению, у меня недостаточно знаний для ваших расчетов, чтобы рекомендовать какой-либо из ваших методов. проблемы вне допустимого диапазона.

...