Углы между двумя n-мерными векторами в Python

Мне нужно определить угол (s) между двумя n-мерными векторами в Python. Например, вход может состоять из двух списков, таких как: [1,2,3,4] и [6,7,8,9] .

  • Поиск подписи под углом между векторами
  • Вычислить угол (по часовой стрелке) между двумя точками
  • 5 Solutions collect form web for “Углы между двумя n-мерными векторами в Python”

     import math def dotproduct(v1, v2): return sum((a*b) for a, b in zip(v1, v2)) def length(v): return math.sqrt(dotproduct(v, v)) def angle(v1, v2): return math.acos(dotproduct(v1, v2) / (length(v1) * length(v2))) 

    Примечание : это произойдет, если векторы имеют одинаковое или противоположное направление. Правильная реализация находится здесь: https://stackoverflow.com/a/13849249/71522

    Примечание : все остальные ответы здесь потерпят неудачу, если два вектора имеют одно и то же направление (например, (1, 0, 0) , (1, 0, 0) ) или противоположные направления (ex, (-1, 0, 0) , (1, 0, 0) ).

    Вот функция, которая будет правильно обрабатывать эти случаи:

     import numpy as np def unit_vector(vector): """ Returns the unit vector of the vector. """ return vector / np.linalg.norm(vector) def angle_between(v1, v2): """ Returns the angle in radians between vectors 'v1' and 'v2':: >>> angle_between((1, 0, 0), (0, 1, 0)) 1.5707963267948966 >>> angle_between((1, 0, 0), (1, 0, 0)) 0.0 >>> angle_between((1, 0, 0), (-1, 0, 0)) 3.141592653589793 """ v1_u = unit_vector(v1) v2_u = unit_vector(v2) return np.arccos(np.clip(np.dot(v1_u, v2_u), -1.0, 1.0)) 

    Используя numpy (настоятельно рекомендуется), вы должны:

     from numpy import (array, dot, arccos, clip) from numpy.linalg import norm u = array([1.,2,3,4]) v = ... c = dot(u,v)/norm(u)/norm(v) # -> cosine of the angle angle = arccos(clip(c, -1, 1)) # if you really want the angle 

    Другая возможность использует только numpy и дает вам внутренний угол

     import numpy as np p0 = [3.5, 6.7] p1 = [7.9, 8.4] p2 = [10.8, 4.8] ''' compute angle (in degrees) for p0p1p2 corner Inputs: p0,p1,p2 - points in the form of [x,y] ''' v0 = np.array(p0) - np.array(p1) v1 = np.array(p2) - np.array(p1) angle = np.math.atan2(np.linalg.det([v0,v1]),np.dot(v0,v1)) print np.degrees(angle) 

    и вот результат:

     In [2]: p0, p1, p2 = [3.5, 6.7], [7.9, 8.4], [10.8, 4.8] In [3]: v0 = np.array(p0) - np.array(p1) In [4]: v1 = np.array(p2) - np.array(p1) In [5]: v0 Out[5]: array([-4.4, -1.7]) In [6]: v1 Out[6]: array([ 2.9, -3.6]) In [7]: angle = np.math.atan2(np.linalg.det([v0,v1]),np.dot(v0,v1)) In [8]: angle Out[8]: 1.8802197318858924 In [9]: np.degrees(angle) Out[9]: 107.72865519428085 

    Использование numpy и устранение ошибок округления BandGap:

     from numpy.linalg import norm from numpy import dot import math def angle_between(a,b): arccosInput = dot(a,b)/norm(a)/norm(b) arccosInput = 1.0 if arccosInput > 1.0 else arccosInput arccosInput = -1.0 if arccosInput < -1.0 else arccosInput return math.acos(arccosInput) 

    Обратите внимание: эта функция генерирует исключение, если один из векторов имеет нулевую величину (деление на 0).

    Python - лучший язык программирования в мире.