将float传递给具有有界域的函数

时间:2017-01-23 05:41:10

标签: python floating-point

我试图计算python2.7中某些向量之间的角度。 我使用以下标识来查找角度。

theta = acos(v。w / | v || w |)

对于特定实例,我的代码是:

var selector = SerialDevice.GetDeviceSelector("COM14");
var informations = await DeviceInformation.FindAllAsync(selector);

if (informations.Any())
{
    var port = await SerialDevice.FromIdAsync(informations.First().Id);
}

当我运行此操作时,我收到错误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)

我认为这是因为acos仅在域[-1,1]上定义,而我的值'a'是一个非常接近1但实际上稍微大一点的浮点数。我可以用ValueError: math domain error确认这一点,我得到1.0000000000000002220446 ......

解决此问题的最佳方法是什么?

我能想到的是检查'a'的值是否大于1(或小于-1)并将它们精确地舍入为1.这似乎是一个俗气的工作。是否有更整洁/更传统的方法来解决这个问题?

1 个答案:

答案 0 :(得分:0)

numpy.clip: 用于Angles between two n-dimensional vectors in Python

如果您重新安排数学,

numpy.nan_to_num:看起来也是一个很好的补丁

并且可以与我的theta = atan2(b,a)公式修改后的代码一起使用,以避免1 + eps acos出现问题(这是我的第一次传递:b = np.nan_to_num(np.sqrt(1 - a ** 2))

但是我的问题就是单独使用点积与acos来解决矢量问题之间的角度问题,特别是在我们有np.cross产品的2和3 D中

我更喜欢形成交叉产品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无论如何,normed args

我认为,除了使用atan2点积“余弦”术语中的信息a时,整数acos项和Dictionary<String, Any>在整体上具有更好的准确性。 {1}}

编辑(有点数学解释,与上面的代码中的a,b,c不同,因为MathJax似乎不是在文本中输入的矢量数学有点混乱在此论坛上启用)

a * b = | a || b | COS(瓦特

c = a x b = | a || b |罪( w c_unit_vector

sqrt( c * c )= | a || b | sin( w ),因为 c_unit_vector * c_unit_vector = 1

所以我们最终得到了atan(| a || b | sin( w ),| a || b | cos( w ))和| a || C |取消atan内部的比率计算