【问题标题】:Rounding logic in Python? [duplicate]Python中的舍入逻辑? [复制]
【发布时间】:2014-07-21 03:54:36
【问题描述】:

在我的原始代码中,我试图从一些浮点值中计算一些索引,但遇到了以下问题:

>>> print int((1.40-.3)/.05)
21

但是:

>>> print ((1.40-.3)/.05)
22.0

我对正在发生的事情说不出话来。谁能解释一下?

【问题讨论】:

标签: python rounding


【解决方案1】:

这是由浮点数不准确引起的:

>>> print repr((1.40-.3)/.05)
21.999999999999996

您可以尝试改用Decimal 类型:

>>> from decimal import Decimal
>>> Decimal
<class 'decimal.Decimal'>

然后

>>> (Decimal('1.40') - Decimal('.3')) / Decimal('.05')
Decimal('22')

fractions.Fraction 类也可以工作。或者,您也可以四舍五入:

>>> round((1.40-.3)/.05, 10) #  round to 10 decimal places
22.0

【讨论】:

  • 尽管人们通常需要任意精度。 21.999999999999996 在大多数实际用途中是 22
  • 用于大多数实际用途,int() 除外
  • Decimal 工作正常......除非它没有。例如,一般为1/d * d != 1。只有当你坚持某些简单的操作时它才是准确的。
  • @Cupitor 不,您可以四舍五入到小数点后 10 位左右。
  • @Cupitor eval?我希望该文件不是来自用户输入,我希望它不能被恶意用户编辑。我建议立即停止它并使用float(如float("12.34"))并改为四舍五入。
【解决方案2】:

删除print,您会看到实际值为:

>>> (1.40-.3)/.05
21.999999999999996

Python 2 print()(更准确地说,float.__str__)通过四舍五入到几个小数位来欺骗你。 Python 3 print()(同样,实际上是 float.__str__)并没有这样做,它总是给出实际值的忠实表示(它缩写,但仅在它不改变值时)。

这种不准确性是浮点数所固有的(包括Decimal,尽管它的不准确性发生在不同的情况下)。这是一个基本问题,不可能表示任意实数。有关说明,请参阅Is floating point math broken?

【讨论】:

  • 我明白了。但“实际”值是 22.0!
  • @Cupitor “实际”是什么意思?
  • 我的意思是表达式的真实(数学)值。
  • @Cupitor 您显然没有阅读您问题下第一条评论中的文章。实数不能用计算机表示,只能表示有理数的一个子集。
  • @Cupitor 关于程序实际处理的价值,这是一个谎言。在这种情况下,四舍五入隐藏了一个非常真实的错误/不准确性,但这不会使错误消失,在其他情况下它会增加错误(例如,对于 1.0/3)。
【解决方案3】:

我认为这可以直截了当地解释:

import decimal

>>> (decimal.Decimal(1.40) -decimal.Decimal(.3))/decimal.Decimal(.05)
Decimal('21.99999999999999722444243843')
>>> (decimal.Decimal('1.40') -decimal.Decimal('.3'))/decimal.Decimal('.05')
Decimal('22')

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-08-05
    • 2020-09-04
    • 1970-01-01
    • 1970-01-01
    • 2016-04-26
    • 1970-01-01
    • 2016-01-23
    • 1970-01-01
    相关资源
    最近更新 更多