2

假设xy都是非常小的数字,但我知道 的真实值x / y是合理的。

最好的计算方法是x/y什么?特别是,我一直在这样做np.exp(np.log(x) - np.log(y),但我不确定这是否会有所作为?

4

2 回答 2

6

根据Python 文档,Python 使用了它所运行的硬件的浮点特性。在当今最常见的机器上,这是 IEEE-754 算术或类似的算法。该 Python 文档并未明确说明舍入模式,但顺便提到样本除法的结果是最接近的可表示值,因此 Python 可能使用舍入到最近的关系到偶数模式。(简称“四舍五入”。如果两个可表示的值在二进制浮点中同样接近,则产生其有效数的低位为零的值。)

在四舍五入模式下的 IEEE-754 算术中,除法的结果是最接近精确数学值的可表示值。既然您说 的数学值x/y是合理的,那么它就在可表示值的正常范围内(不低于它,处于亚正常范围内,精度会受到影响,而不是高于它,结果四舍五入到无穷大)。在正常范围内,基本运算的结果将在格式的正常精度范围内准确。

然而,由于xy是“非常小的数”,我们可能会担心它们是次正规的,并且在执行除法之前已经损失了精度。在 IEEE-754 基本 64 位二进制格式中,低于 2 -1022(约 2.22507•10 -308)的数字是不正常的。如果xy小于那个值,那么它们已经损失了精度,除了偶然之外,没有任何方法可以从中得出正确的商。用对数计算商将无济于事。

如果您正在运行的机器碰巧没有使用 IEEE-754,那么x/y直接计算仍然可能会产生比np.exp(np.log(x)-np.log(y)). 前者是在硬件中计算基本功能的单一操作,可能是经过合理设计的。后者是在软件中计算复杂功能的几种操作,使用普通的硬件操作难以准确计算。

对浮点运算存在相当多的不安和不信任。缺乏知识似乎导致人们害怕他们。但是这里应该理解的是,基本的浮点运算定义得非常好,并且在正常范围内是准确的。浮点计算的实际问题来自运算序列上舍入误差的累积、复合误差的内在数学以及对结果的不正确预期。这意味着无需担心单个划分的准确性。相反,应该牢记浮点的整体使用。(如果您的问题提供更多上下文,说明为什么这种划分很重要,如何x以及y已经从先前的数据中产生,以及总体目标是什么。)

笔记

与 IEEE-754 的一个常见偏差是将次正常值刷新为零。如果你有一些xy正常的,一些实现可能会在对它们执行操作之前将它们刷新为零。但是,这在 SIMD 代码中比在普通标量编程中更常见。而且,如果发生这种情况,它会阻止您进行评估np.log(x),并且np.log(y)无论如何,因为在这些情况下,低于正常值的值也会被刷新为零。所以我们很可能会排除这种可能性。

于 2018-01-10T14:16:04.393 回答
0

除法与其他 IEEE-754 指定的操作一样,以无限精度计算,然后(使用普通舍入规则)舍入到最接近的可表示浮点数。计算结果x/y几乎肯定会比计算结果准确得多np.exp(np.log(x) - np.log(y)(并且保证不会降低准确度)。

于 2018-01-10T12:31:34.880 回答