【问题标题】:Testing for rounding errors due to Floating Point limitations测试因浮点限制导致的舍入误差
【发布时间】:2019-01-21 05:54:41
【问题描述】:

我最近了解到浮点的主要限制之一:某些数字无法以二进制正确表示,因此可能给出的答案对于您的目的来说不够准确。

知道round(2.675, 2)round(2.665, 2) 都等于2.67,我尝试编写一些代码来给出具有此属性的数字列表(不正确地四舍五入)。

请参阅下面或此副本中的我的代码: https://repl.it/@FTBlover123/Float-Rounding-Test

Test = True
number1 = 0.005
number2 = 0.015
count = 0
count_per_test = 5
while Test:
    if round(number1, 2) == round(number2, 2):
        print number1, number2, round(number1, 2), round(number2, 2)
        count += 1
    else:
        pass
    number1 += 0.005
    number2 += 0.005
    if count == count_per_test:
        answer = raw_input("End Program? Y / N: ")
        if answer == "Y":
            print "Program Ended"
            Test = False
        elif answer == "N":
            print "Searching For %s more rounding errors" % (count_per_test)
            count = 0
        else:
            print "Error, raw_input incorrect"
            Test = False

#2.675 is a known number with a rounding error.
print 2.665, 2.675, round(2.675, 2), round(2.665, 2)
#79.705 should have one according to the results, but it doesn't truly.
print 79.695, 79.705, round(79.695, 2), round(79.705, 2)

最后的 2 个prints 就是其中之一。

尽管由于浮点数的限制,代码确实似乎返回了一些舍入错误,但这些似乎不是真实值(第一个除外)。 这是因为我使用的是浮点 0.005(不能用二进制表示),它本身会导致新的 number1number2 成为其已经不准确的自我的不正确版本!这很容易通过将 number1number2 递增 0.001(也不能用二进制表示)来证明,因为这也会导致答案仍然不正确,但也不同!

因此,我的问题:

是否有可能创建代码来正确检查由于浮点限制导致的舍入错误,而不会遭受我们试图测试的确切缺陷的影响? (尽管此类示例库也将不胜感激,但我对修复代码更感兴趣)

我的错误输出之间的间隔似乎呈指数级增长。

  • 0.005 0.015 0.01 0.01
  • 0.035 0.045 0.04 0.04
  • 1.025 1.035 1.03 1.03
  • 21.535 21.545 21.54 21.54

  • 79.695 79.705 79.7 79.7

  • 9164.075 9164.085 9164.08 9164.08

  • 36933.455 36933.465 36933.46 36933.46

这是什么原因造成的?对于正确的不正确舍入的浮点数也是如此吗?

【问题讨论】:

    标签: python python-2.7 floating-point binary rounding


    【解决方案1】:

    好吧,正如您所注意到的,您不能只添加 0.005,因为 0.005 不能表示为浮点数。

    该怎么做呢?使用可表示的数字!

    2675 可以精确地表示为浮点数(最多 2^53 的每个整数),1000 也是如此。所以2675.0/1000.0,虽然不能表示为浮点数,四舍五入到最接近的可表示浮点数,就像文字 2.675 一样。 (就此而言,您可以使用267.5/100.0,但我认为最好坚持使用整数。)

    因此,不要以这种方式增加您打算检查的值,而是增加分子,然后每次都进行除法。

    【讨论】:

    • Python 没有关于浮点的严格规范。浮点行为依赖于实现,实现通常依赖于底层平台。所以不能保证连续可表示整数的结尾是否为 2^53。现在很常见,但实现可能会选择使用更宽或更窄的浮点格式,并且他们可能会在支持它的硬件上选择十进制格式(或者如果他们有特殊目的选择它)。
    【解决方案2】:

    首先,有关python内部浮点运算的更多信息请阅读this。因为您的示例使用相同的值(舍入 2.675 并得到 2.67,但您期望 2.68),您可能已经阅读过此文档。

    现在我试着回答你的一些问题:

    问:是否可以创建检查...的代码?

    A:是的,但你需要使用浮点数以外的其他算法。在您的情况下,如果您想检查为什么该值被向下舍入,您可以使用小数模块查看该值的浮点表示。

    您写“根据结果,79.705 应该有一个,但事实并非如此。”

    这是不正确的:

    >>> from decimal import Decimal
    >>> t = 79.695
    >>> print (Decimal(t))
    79.69499999999999317878973670303821563720703125
    

    如您所见,内部浮点表示与十进制值不同,因为如果您对这些值使用“打印”之类的东西,python 已经四舍五入了。 如果“普通”二进制浮点运算不够好,该模块也可用于十进制浮点运算。

    问题是,你为什么想要一个包含这些数字的列表?因为大多数时候,表示错误是完全没有问题的。只有一些cases 需要考虑这个问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-09-01
      • 1970-01-01
      • 2020-08-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-09-19
      相关资源
      最近更新 更多