使用math.acos计算两向量夹角时触发ValueError: math domain error
解决math.acos计算向量夹角的定义域错误问题
问题根源
你用的x1和x2是完全相反的向量,理论上它们的余弦值应该是-1,但浮点数运算存在精度误差,实际算出来的c可能会略小于-1(比如-1.0000000000000002),而math.acos()只接受[-1, 1]之间的参数,超出这个范围就会抛出ValueError: math domain error。
两种解决办法
办法一:把余弦值限制在合法范围
用numpy.clip()把计算出的c强行限定在[-1, 1]内,修改后的代码:
import numpy as np from math import acos, sqrt x1 = np.array([12.001, 13.001, 14.001]) x2 = np.array([-12.001, -13.001, -14.001]) mom1 = sqrt(x1.dot(x1)) mom2 = sqrt(x2.dot(x2)) son = x1.dot(x2) c = son / mom1 / mom2 # 修正余弦值范围 c = np.clip(c, -1.0, 1.0) theta_rad = acos(c)
办法二:直接用numpy的arccos函数
numpy自带的arccos会自动处理这种浮点数精度导致的微小越界问题,代码更省事:
import numpy as np x1 = np.array([12.001, 13.001, 14.001]) x2 = np.array([-12.001, -13.001, -14.001]) # 一步计算余弦值和夹角 cos_theta = np.dot(x1, x2) / (np.linalg.norm(x1) * np.linalg.norm(x2)) theta_rad = np.arccos(cos_theta)
如果想更稳妥,也可以结合clip和np.arccos,写成theta_rad = np.arccos(np.clip(cos_theta, -1, 1))。
内容的提问来源于stack exchange,提问作者jason
相关产品推荐
相关产品推荐

