浮点格式化的Python精度问题

时间:2018-03-14 02:10:45

标签: python floating-point precision

请查看我在Python 3.6解释器中输入的以下Python代码:

>>> 0.00225 * 100.0
0.22499999999999998
>>> '{:.2f}'.format(0.00225 * 100.0)
'0.22'
>>> '{:.2f}'.format(0.225)
'0.23'
>>>  '{:.2f}'.format(round(0.00225 * 100.0, 10))
'0.23'

希望你能立刻明白我为何感到沮丧。我试图在我的GUI上显示value * 100.0,在单元格后面存储完整的精度,但只显示2个小数点(或者用户的精度设置是什么)。 GUI类似于Excel电子表格。

我不想丢失0.22222444937645之类的精确度并且10舍入,但我也不希望显示0.00225 * 100.0这样的值为0.22

我有兴趣了解接近这种情况的标准方法或针对我的具体情况的补救措施。提前感谢您的帮助。

2 个答案:

答案 0 :(得分:2)

考虑使用Decimal module,其中"支持快速正确舍入的十进制浮点运算。"与您的用例相关的Decimal的主要优点是:

  
      
  • 十进制数字可以准确表示。相比之下,像1.12.2这样的数字在二进制浮点中没有精确的表示。最终用户通常不希望1.1 + 2.2显示为3.3000000000000003,因为它与二进制浮点显示。

  •   
  • 准确性延续到算术中。在十进制浮点数中,0.1 + 0.1 + 0.1 - 0.3恰好等于零。在二进制浮点数中,结果为5.5511151231257827e-017。虽然接近于零,但差异阻止了可靠的相等性测试,并且差异可能会累积。因此,在具有严格相等不变量的会计应用程序中,decimal是首选。

  •   

根据您在问题中提供的信息,我无法说明迁移到Decimal需要进行多少大修。但是,如果您正在创建类似电子表格的应用程序并且始终希望保留最大精度,那么您可能希望重新构建迟早使用Decimal以避免面向用户的GUI中出现意外数字。

要获得所需的行为,您可能需要更改ROUND_HALF_EVEN个实例的舍入模式(默认为Decimal)。

from decimal import getcontext, ROUND_HALF_UP

getcontext().rounding = ROUND_HALF_UP

n = round(Decimal('0.00225') * Decimal('100'), 2)
print(n)  # prints Decimal('0.23')

m = round(Decimal('0.00225') * 100, 2)
print(m)  # prints Decimal('0.23')

答案 1 :(得分:-2)

也许使用小数? docs.python.org/2/library/decimal.html

from decimal import *
getcontext().prec = 2
n = Decimal.from_float(0.00225)
m = n * 100
print(n, m)
print(m.quantize(Decimal('.01'), rounding=ROUND_DOWN))
print(m.quantize(Decimal('.01'), rounding=ROUND_UP)