【问题标题】:Python representation of floating point numbers [duplicate]浮点数的Python表示[重复]
【发布时间】:2013-08-10 02:00:16
【问题描述】:

我今天花了一个小时试图找出原因

return abs(val-desired) <= 0.1

偶尔会返回False,尽管valdesired 的绝对差异为&lt;=0.1。经过一番调试,我发现-13.2 + 13.3 = 0.10000000000000142。现在我明白了 CPU 不能轻易表示大多数实数,但这是一个例外,因为你可以减去 0.00000000000000142 并得到 0.1,所以它可以用 Python 表示。

我在 Intel Core 架构 CPU 上运行 Python 2.7(这是我能够测试的全部)。我很想知道如何存储0.1 的值,尽管无法将算术应用于特定的浮点值。 valdesiredfloat 值。

【问题讨论】:

  • 你会发现这很有用:floating-point-gui.de
  • 我知道 CPU 不能轻易地以高分辨率表示大多数浮点数 ...您完全误解了,浮点数都是 [暂时忘记整数] CPU 可以表示,并且它们可以以它们所能达到的全部精度来表示它们。现在,如果您将 floating-point 替换为 real 您的理解会更正确。
  • 这个问题每天都会被问好几次,无论是对于 python、C、Java 还是其他任何东西。 -1 在浪费其他成员的时间之前没有搜索它。 0.1 不能在浮点数(单精度或双精度)中精确表示,因此必须存在误解或 fpu 之外的机制会产生精确的 0.1 值。
  • @moooeeeep:这不是那个问题的重复。再次阅读问题。 OP 指出这 被理解的。不明白的是结果的准确性。
  • @BlackBear 为这个添加书签,不像经常被引用的 Goldberg document 那样笨拙

标签: python floating-accuracy


【解决方案1】:

要直接解决您的问题“当我有不精确的浮点数时,我如何存储像 0.1 这样的值并与之进行精确比较”,答案是使用不同的类型来表示您的数字。 Python 有一个decimal 模块,用于进行十进制定点和浮点数学运算,而不是二进制——显然,在十进制中,0.1、-13.2 和 13.3 都可以精确表示而不是近似表示;或者您可以在使用小数进行计算时设置特定的精度级别,并丢弃低于该重要性级别的数字。

val = decimal.Decimal(some calculation)
desired = decimal.Decimal(some other calculation)
return abs(val-desired) <= decimal.Decimal('0.1')

另一种常见的替代方法是通过人工乘以十的幂来使用整数而不是浮点数。

return not int(abs(val-desired)*10)

【讨论】:

    【解决方案2】:

    是的,这可能有点令人惊讶:

    >>> +13.3
    13.300000000000001
    >>> -13.2
    -13.199999999999999
    >>> 0.1
    0.10000000000000001
    

    所有这些数字都可以用大约 16 位的精度表示。那为什么:

    >>> 13.3-13.2
    0.10000000000000142
    

    为什么在这种情况下只有 14 位的准确度?

    嗯,这是因为 13.3 和 -13.2 有 16 位精度,这意味着 14 个小数点,因为小数点前有两位数。所以结果也有 14 个小数点的精度。即使计算机可以用 16 位数字表示数字。

    如果我们将数字变大,结果的准确性会进一步降低:

    >>> 13000.3-13000.2
    0.099999999998544808
    
    >>> 1.33E10-13.2E10
    -118700000000.0
    

    简而言之,结果的准确性取决于输入的准确性。

    【讨论】:

    • 我同意你的解释,但我认为中间部分(包含你答案的症结所在)并不是很容易理解。问题是,一个 IEEE754 double 总共可以表示 16 位数字,即小数点 leftright 数字之和。与您的 14 decimal points 相同,但在解释这里发生的事情时可能更清楚一些?
    • 确实,要理解的重要部分不仅是浮点的精度有限(relative 误差约为 2e-16),而且这个误差会通过减法放大两个大数。这两个数字都有大约 13 * 2e-16 的 绝对 误差,因此差异将具有 2 * 13 * 2e-16 的潜在 绝对 误差。由于减法的标称解是 0.1,这在 2 * 13 * 2e-16 / 0.1 = 5e-14 的答案中给出了相对错误。因此,表示 13.3 的 relative 小误差被放大了 100 多倍!。
    • 我更新了,希望越来越好。
    【解决方案3】:

    “现在我明白了 CPU 不能轻易地以高分辨率表示大多数浮点数”,你问这个问题的事实表明你不明白。实数值 13.2、13.3 和 0.1 都不能完全表示为浮点数:

    >>> "{:.20f}".format(13.2)
    '13.19999999999999928946'
    >>> "{:.20f}".format(13.3)
    '13.30000000000000071054'
    >>> "{:.20f}".format(0.1)
    '0.10000000000000000555'
    

    【讨论】:

    • 我认为 OP 明白这一点。据我了解,问题是为什么结果的准确性低于计算机可以表示的准确度。
    猜你喜欢
    • 2011-08-10
    • 2011-02-09
    • 1970-01-01
    • 2011-02-28
    • 1970-01-01
    • 1970-01-01
    • 2015-04-02
    • 2018-04-29
    相关资源
    最近更新 更多