在Python中'正确'舍入到小数点后3位

use*_*282 5 python python-2.7

我可能会遗漏一些必要的东西,但是我无法找到一种方法来"正确地"在Python(2.7)中对浮点数/小数点进行舍入,至少小数点后三位.通过'正确',我的意思是1.2225应该舍入到1.223,并且1.2224应该舍入到1.222.

我知道round在设计中不能用于Python中的浮点数,但我似乎无法Decimal按预期行事,也不能按ceil功能行事.寻找内置功能而不是自定义功能变通方法,但两者都是开放的.

>>> x = 1.2225                                   # expected: 1.223
>>> round(x, 3)               
1.222                                            # incorrect

>>> from math import ceil

>>> ceil(x * 1000.0) / 1000.0
1.223                                            # correct
>>> y = 1.2224                                   # expected: 1.222
>>> ceil(y * 1000.0) / 1000.0 
1.223                                            # incorrect

>>> from decimal import Decimal, ROUND_UP, ROUND_HALF_UP

>>> x = Decimal(1.2225)
>>> x.quantize(Decimal('0.001'), ROUND_UP)
Decimal('1.223')                                 # correct
>>> y = Decimal(1.2224)
>>> y.quantize(Decimal('0.001'), ROUND_UP)
Decimal('1.223')                                 # incorrect

>>> y.quantize(Decimal('0.001'), ROUND_HALF_UP)
Decimal('1.222')                                 # correct
>>> x.quantize(Decimal('0.001'), ROUND_HALF_UP)
Decimal('1.222')                                 # incorrect
Run Code Online (Sandbox Code Playgroud)

有没有办法获得理想的结果?

pok*_*oke 10

问题是,这Decimal(1.2225)不是你所期望的:

>>> Decimal(1.2225)
Decimal('1.2224999999999999200639422269887290894985198974609375')
Run Code Online (Sandbox Code Playgroud)

您正在使用浮点数来创建小数,但该浮动对于您的用例来说已经太不精确了.正如你所看到的,它实际上是一个1.222499小于,因此它1.2225会正确地向下舍入.

为了解决这个问题,您需要通过将它们作为字符串传递来创建具有正确精度的小数.一切都按预期工作:

>>> x = Decimal('1.2225')
>>> x.quantize(Decimal('0.001'), ROUND_HALF_UP)
Decimal('1.223')
>>> y = Decimal('1.2224')
>>> y.quantize(Decimal('0.001'), ROUND_HALF_UP)
Decimal('1.222')
Run Code Online (Sandbox Code Playgroud)