Python的epsilon值是否正确?

时间:2014-04-21 02:41:18

标签: python numpy numeric numerical-methods

根据Wikipedia

  

机器epsilon被定义为最小数字,当添加到一个数字时,产生的结果不同于一个

在Python中,可以使用sys.float_info.epsilon找到epsilon并返回相当于2 ^ -52的值。但是,我可以将任何大于2 ^ -53的数字添加到1并仍然得到不同的结果。 但是通过上面的epsilon定义,将任何小于epsilon的值添加到一个应该给出一个。 这是否意味着sys.float_info.epsilon返回的值不正确,或者Python正在使用epsilon的其他定义?

以下代码说明了这一点,浮点数以十六进制格式打印出来。

import sys
import numpy
print 'epsilon=%g' % sys.float_info.epsilon
# output: 2.22045e-16
epsilon = sys.float_info.epsilon
print 'epsilon(hex) = %s' % float.hex(epsilon)
# output:  0x1.0000000000000p-52

one = numpy.float64(1.0)

delta = float.fromhex('0x1.fffffffffffffp-53')
print 'delta = %s' % float.hex(delta)

print 'epsilon - delta = %s' % (float.hex(epsilon-delta))
#output: 0x1.0000000000000p-105

print '\n1.0 + epsilon = %s' % (float.hex(one+numpy.float64(epsilon)))
#output: 0x1.0000000000001p+0

print '\n1.0 + delta = %s' % (float.hex(one+numpy.float64(delta)))
#output: 0x1.0000000000001p+0
# since delta is smaller than epsilon, I expected 0x1.0000000000001p+0

delta1 = float.fromhex('0x1.0000000000001p-53')
print '\n1.0 + %s = %s' % (float.hex(delta1), float.hex(one+delta1))
#output: 0x1.0000000000001p+0
# since delta is smaller than epsilon, I expected 0x1.0000000000001p+0

delta2 = float.fromhex('0x1.0000000000000p-53')
# note: delta2 = epsilon / 2.0
print '\n1.0 + %s = %s' % (float.hex(delta2), float.hex(one+delta2))
# 0x1.0000000000000p+0

结果输出

epsilon=2.22045e-16
epsilon(hex) = 0x1.0000000000000p-52
delta = 0x1.fffffffffffffp-53
epsilon - delta = 0x1.0000000000000p-105

1.0 + epsilon = 0x1.0000000000001p+0

1.0 + delta = 0x1.0000000000001p+0

1.0 + 0x1.0000000000001p-53 = 0x1.0000000000001p+0

1.0 + 0x1.0000000000000p-53 = 0x1.0000000000000p+0

2 个答案:

答案 0 :(得分:3)

我认为你所看到的是Python float类型在精度不足时如何处理舍入。您引用的描述epsilon的维基百科文本似乎将此部分排除在外。

在您的示例中,1 + delta向上舍入为1 + epsilon。即使float可以指定deltaepsilon之间的差异,也不能代表1 + delta1 + epsilon之间的差异。正如您所注意到的(使用delta2测试),最小数字向下舍入为1而不是1 + epsilon似乎为1 + epsilon/2

因此,对epsilon在Python中的含义的正确定义可能是:

epsilon是最小的正浮点数,(1 + epsilon) - 1等于epsilon

答案 1 :(得分:1)

这个定义是错误的:机器epsilon 是数字eps,使得1 + eps是1之后的下一个数字。因此,对于标准舍入,u = eps / 2是添加时的最小数字1表示大于1的值。此数量u通常称为单位舍入机器单位。 (对于IEEE64,eps = 2 ^( - 52),u = 2 ^( - 53)。)

顺便说一句,对于大多数实际用途,单位舍入u比eps更有用:例如,u是将值四舍五入到标准化机器号时的最大相对误差。

参考:Higham,数值算法的准确性和稳定性,第37,38页。