根据Wikipedia:
Machine epsilon is defined as the smallest number that, when added to one, yields a result different from one
在Python中,epsilon可以使用sys.float_info.epsilon
找到,并返回一个相当于2^-52的值。但是,我可以将大于2^-53的任何数字加到1,仍然得到与1不同的结果。
但是根据上面对epsilon的定义,加上任何小于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
我认为您所看到的是Python的
float
类型在精度不足时如何处理舍入。你引用的描述epsilon
的维基百科文本似乎忽略了这一部分。在您的示例中,
1 + delta
被取整为1 + epsilon
。尽管float
可以指定delta
和epsilon
之间的差异,但它不能表示1 + delta
和1 + epsilon
之间的差异。正如您所注意到的(通过您的delta2
测试),向下舍入到1
而不是向上舍入到1 + epsilon
的最大数字似乎是1 + epsilon/2
。因此,正确定义Python中
epsilon
的含义可能是:epsilon
是最小的正浮点数,因此(1 + epsilon) - 1
等于epsilon
。这个定义是错误的:机器epsilon是eps的数字,因此1+eps是1之后的下一个数字。因此,对于标准四舍五入,u=eps/2是添加到1时给出大于1的值的最小值。这个数量u通常被称为单位舍入或机器单位。 (对于IEEE64,eps=2^(-52),u=2^(-53)
顺便说一下,在大多数实际应用中,单位舍入u比eps更有用:例如,u是值舍入为标准化机床号时的最大相对误差。
参考文献:Higham,数值算法的精度和稳定性,第37、38页。
相关问题 更多 >
编程相关推荐