提问人:user22524802 提问时间:9/9/2023 更新时间:9/9/2023 访问量:72
四元数计算中小浮点数的 Python 除法
Python division of small floats in quaternion calculations
问:
考虑数学方程:y = (sin(x/2)/x),它出现在旋转的计算中。在 x->0 的限制中,其值为 1/2。在 Python(或任何具有类似 64 位浮点类型的语言)中实现这一点似乎适用于除 x = 0.0 之外的所有值。
然而,当这个数学出现在书中时,通常建议使用截断的泰勒级数展开来实现该函数,该展开没有除以零的问题。下面是 SciPy 中的一个示例,其中为此逻辑选择了看似任意的 1e-3 弧度阈值。
基本实现似乎适用于较小的 x 值(显然除了 x = 0.0)。这里真的有精度问题需要关注吗?如果是这样,显示它的测试用例是什么?y = np.sin(x/2)/x
将 0.0 作为特例检查的代码比使用具有任意阈值的截断泰勒级数更简洁。
答:
基本实现似乎适用于较小的 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
(缺少 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 中讨论它。我不知道为什么选择这个特定的阈值。
评论
x/2!=0.0
x