【问题标题】:Is Python's epsilon value correct?Python 的 epsilon 值是否正确?
【发布时间】:2014-06-05 01:58:15
【问题描述】:

根据Wikipedia

机器 epsilon 被定义为加一时产生不同于一的结果的最小数

在 Python 中,可以使用 sys.float_info.epsilon 找到 epsilon,并返回一个等于 2^-52 的值。但是,我可以将任何大于 2^-53 的数字加到 1 上,但仍然得到与 1 不同的结果。 但是根据上面对 epsilon 的定义,将任何小于 epsilon 的值加到 1 应该得到 1。 这是否意味着 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 numpy numeric numerical-methods


    【解决方案1】:

    该定义是错误的:ma​​chine epsilon 是数字 eps,因此 1+eps 是 1 之后的下一个数字。因此,在标准四舍五入下,u = eps/2 是相加时的最小数字到 1 给出大于 1 的值。这个量 u 通常称为 unit roundoffma​​chine unit。 (对于 IEEE64,eps=2^(-52),u = 2^(-53)。)

    顺便说一下,对于大多数实际用途,单位舍入 u 比 eps 更有用:例如,当一个值舍入为标准化机器数时,u 是最大相对误差。

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

    【讨论】:

      【解决方案2】:

      我认为您所看到的是 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

      【讨论】:

      • 我认为这不是 Python 的规则,而是 IEEE 的。我喜欢你的结论,除了零也符合要求。也许如果您将其重述为“最小的 nonzero 浮点...”
      • 关于零的好点。事实上,-2/epsilon (-2**53) 可能也算数(虽然在“更接近负无穷大”的意义上“更小”),所以我调整了我的定义以指定一个正数。
      猜你喜欢
      • 2012-03-20
      • 2015-06-24
      • 1970-01-01
      • 1970-01-01
      • 2014-04-29
      • 2015-09-26
      • 1970-01-01
      • 2011-04-16
      • 1970-01-01
      相关资源
      最近更新 更多