四元数计算中小浮点数的 Python 除法

Python division of small floats in quaternion calculations

提问人:user22524802 提问时间:9/9/2023 更新时间:9/9/2023 访问量:72

问:

考虑数学方程:y = (sin(x/2)/x),它出现在旋转的计算中。在 x->0 的限制中,其值为 1/2。在 Python(或任何具有类似 64 位浮点类型的语言)中实现这一点似乎适用于除 x = 0.0 之外的所有值。

然而,当这个数学出现在书中时,通常建议使用截断的泰勒级数展开来实现该函数,该展开没有除以零的问题。下面是 SciPy 中的一个示例,其中为此逻辑选择了看似任意的 1e-3 弧度阈值。

https://github.com/scipy/scipy/blob/9d5d4f86bd50e11ee6e593758ab06f9b6f7cf021/scipy/spatial/transform/_rotation.pyx#L1102

基本实现似乎适用于较小的 x 值(显然除了 x = 0.0)。这里真的有精度问题需要关注吗?如果是这样,显示它的测试用例是什么?y = np.sin(x/2)/x

将 0.0 作为特例检查的代码比使用具有任意阈值的截断泰勒级数更简洁。

Python 浮点 精度 四元数 scipy-spatial

评论

0赞 chtz 9/9/2023
我会检查,否则你会得到非常接近零的零。x/2!=0.0x
0赞 Eric Postpischil 9/9/2023
“表现良好”的函数可以用多项式在区间内近似。各种因素都会影响多项式的工程设计——较大的区间会降低精度,较高的度数会提高精度,但也会增加计算时间,以及您是否针对最小绝对误差、最小相对误差或其他属性设计多项式......
0赞 Eric Postpischil 9/9/2023
...一旦您为多项式选择了目标,在计算函数为 sin(x/2)/x 与自定义多项式之间设置阈值的一种方法可能是,在相同精度下,阈值引起的区间导致大约相等的工作量。例如,使用 sin(x/2)/x 测量需要多少时间,计算出在同一时间内可以计算出多项式的次数,测试各种区间以找出可以使区间多大,精度与使用 sin(x/2)/x 相同。
0赞 Eric Postpischil 9/9/2023
实现上述内容需要使用软件生成最小最大多项式(或您正在使用的任何其他多项式近似值)的一些工作,这在 Stack Overflow 中需要讨论。有关于实现基本函数的书籍和其他资源,适用于此。

答:

1赞 Nick ODell 9/9/2023 #1

基本实现似乎适用于较小的 x 值(显然除了 x = 0.0)。这里真的有精度问题需要关注吗?如果是这样,显示它的测试用例是什么?y = np.sin(x/2)/x

是的。您可以在以下代码示例中看到这一点:

>>> angle = 5e-324
>>> np.sin(angle/2)/angle
0.0

更一般地说,这是从 -5e-322 到 5e-322 绘制的函数。回想一下,sin(x/2)/x 接近 0 时的极限是 1/2,因此此图应该是一条几乎笔直的水平线,在 y=0.5 处,中间有一个缺失值。np.sin(x/2)/x

sin(x/2)/x near zero

(缺少 X 轴,因为当您尝试绘制极小的 X 值时,matplotlib 会吓坏了。

数字 5e-324 是一个极端情况,因为 5e-324 / 2 不能表示为浮点数,但之后的数字也不是很好。在x=2.5e-321左右之前,计算并不总是精确到小数点后三位。np.sin(x/2)/x

将 0.0 作为特例检查的代码比使用具有任意阈值的截断泰勒级数更简洁。

我不同意 - 使用浮点数学并检查与零完全相等的代码几乎总是代码味道。通常,如果代码在输入正好为零时被零除以零,则在接近零的值时,它在数值上是不稳定的。

下面是 SciPy 中的一个示例,其中为此逻辑选择了看似任意的 1e-3 弧度阈值。

我翻阅了 SciPy 的历史,以找出为什么阈值专门设置为 1e-3。在最初添加 1e-3 阈值的提交中,没有任何关于为什么选择该值的讨论,也没有在关联的 PR 中讨论它。我不知道为什么选择这个特定的阈值。

评论

0赞 Tim Roberts 9/9/2023
我们不应该承认这样的答案,但我想祝贺你对一个许多程序员默默忽略的难题进行了全面、明确的描述。干得好。