2017-01-23 1 views
0

Я пытаюсь вычислить угол между некоторыми векторами в python2.7. Я использую следующий идентификатор, чтобы найти угол.Передача float функции с ограниченным доменом

тета = экоса (v ж/| v || ш |.)

Для конкретного экземпляра мой код:

v = numpy.array([1.0, 1.0, 1.0]) 
w = numpy.array([1.0, 1.0, 1.0]) 
a = numpy.dot(v, w)/(numpy.linalg.norm(v) * numpy.linalg.norm(w)) 
theta = math.acos(a) 

Когда я запускаю это я получаю ошибку ValueError: math domain error

Я предполагаю, что это потому, что acos определяется только в домене [-1,1], а мое значение «a» - это float, который очень близок к 1, но на самом деле немного больше. Я могу подтвердить это с помощью print Decimal(a), и я получу 1.0000000000000002220446 ...

Каков наилучший способ обойти эту проблему?

Все, что я могу придумать, это проверить, что любые значения 'a' больше 1 (или меньше -1) и округляют их до точности 1. Это похоже на липкую работу. Есть ли более аккуратный/более обычный способ решения этой проблемы?

ответ

0

numpy.clip: был использован в Angles between two n-dimensional vectors in Python

numpy.nan_to_num: также выглядит как хороший патч, если вы вновь организовать математику

и могут быть использованы с кодом модифицированного моей theta = atan2(b,a) формулировки, чтобы избежать 1 + eps проблем с acos (это был мой мой 1-й проход с: b = np.nan_to_num(np.sqrt(1 - a ** 2)))

Но у меня есть проблемы с почти универсальным использованием продукта-точки только с acos для угла между проблемой векторов, в частности, в 2 и 3 D, где мы имеем np.cross продукта

Я предпочитаю, образующим векторное произведению b «синусоидальных» термин, проходя как ненормированный a «косинус» термина и мой b к atan2 :

import numpy as np 
v = np.array([1.0, 1.0, 1.0]) 
w = np.array([1.0, 1.0, 1.0]) 

a = np.dot(v, w) 
c = np.cross(v, w) 
b = np.sqrt(np.dot(c,c)) 

theta = np.arctan2(b,a) 

atan2(b, a) формулировка не будет сгенерировано исключение с 1 + eps ошибок с плавающей точкой с linalg.norm плавающей точкой допуска, если вы используете нормированный арг - и atan2 не нуждается в нормированных арг равно

Я считаю, что это более численно прочным с перекрестным произведением b термин и atan2 дают лучшую точность в целом, чем просто используя информацию в произведении «косинус» термин a точки с acos

редактировать: (немного Math объяснений, не то же самое а, б, как в приведенном выше коде, несколько перепутал вектор математику набранный в тексте, так как MathJax, кажется, не будет включен на этом форуме)

* б = | a || b | сов (ш )

гр = хб = | а || Ь | Грех (ж) c_unit_vector

SQRT (с * с) = | || Ь | Грех (ж), так как c_unit_vector * c_unit_vector = 1

так что мы в конечном итоге с Atan (| а || Ь | sin (ж), | а || Ь | соз (ш)) и | a || b | отменить в расчете отношения внутреннее значение atan

+0

Я реализовал это загадочное решение. Он работает хорошо (спасибо), но как он работает? Похоже, что это займет угол между проекцией одного вектора на другой и ортогональным. – Jemma

Смежные вопросы