防止Python中浮点除法的下溢

时间:2018-01-10 04:10:58

标签: python floating-point precision underflow

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

计算x/y的最佳方式是什么? 特别是,我一直在做np.exp(np.log(x) - np.log(y),但我不确定这是否会产生影响?

2 个答案:

答案 0 :(得分:3)

根据Python documentation,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))更好的结果。前者是计算硬件基本功能的单一操作,可能是合理设计的。后者是在软件中计算复杂功能的几种操作,使用常见的硬件操作很难准确。

对浮点运算存在相当大的不安和不信任。缺乏知识似乎导致人们害怕他们。但是,这里应该理解的是,基本浮点运算非常明确,并且在正常范围内是准确的。浮点计算的实际问题来自于累积操作序列的舍入误差,复杂错误的固有数学以及对结果的错误预期。这意味着没有必要担心单个部门的准确性。相反,应该牢记浮点的整体使用。 (如果提出更多背景信息,可以更好地回答您的问题,阐明为什么这种划分很重要,如何从先前数据生成xy,以及总体目标是什么。)

注意

与IEEE-754的不同寻常的偏差是将次正常值刷新为零。如果您有一些x和一些y是次正规的,那么某些实现可能会在对它们执行操作之前将它们刷新为零。但是,这在SIMD代码中比在正常的标量编程中更常见。并且,如果它正在发生,它将阻止您无论如何评估np.log(x)np.log(y),因为在这些中也会将次正常值刷新为零。所以我们可以忽略这种可能性。

答案 1 :(得分:0)

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