I want to calculate the cosine of the angle of two 2D-vectors that lie on the same plane in Python. I use the classic formula cosθ = v1∙v2/(|v1||v2|). However, depending on how I implement it, the rounding errors can give values greater than 1 or less than -1 for parallel vectors. Three examples of the implementation follow:
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))
When I execute this code on my machine (Python 3.7.6, Numpy 1.18.1), I get:
-1.0 -1.0000000000000002 -1.0
The difference between the 2nd and 3rd version of the function is especially weird to me...
If I use the second function to calculate the angle via the inverse cosine, I will get a nan, which I want to avoid (and I don't want to check every time, if the result lies in [-1,1]). I was wondering though whether versions 1 and 3 (which give the correct result) are numerically stable in all cases.