在Python中'适当'舍入到小数点后3位

时间:2021-07-18 16:35:54

I may be missing something essential, but I can't figure out a way to 'properly' round floats/Decimals in Python (2.7), at least to three decimal places. By 'properly' I mean that 1.2225 should round to 1.223, and 1.2224 should round to 1.222.

我可能会遗漏一些必要的东西,但我无法找到一种方法来“正确”地将Python(2.7)中的浮点数/小数值舍入,至少小数点后三位。通过'正确',我的意思是1.2225应该舍入到1.223,而1.2224应该舍入到1.222。

I know round won't work for floats in Python, by design, but I can't seem to get Decimal to behave as expected, nor the ceil function. Looking for built-in functionality rather than custom function workarounds preferably, but open to both.

我知道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

Is there a way to get the desired result?

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

3 个解决方案

#1


7  

The problem is that Decimal(1.2225) is not what you expect it to be:

问题是Decimal(1.2225)不是你所期望的那样:

>>> Decimal(1.2225)
Decimal('1.2224999999999999200639422269887290894985198974609375')

You are using a float to the create the decimal, but that float is already too imprecise for your use case. As you can see, it’s actually a 1.222499 so it is smaller than 1.2225 and as such would correctly round down.

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

In order to fix that, you need to create decimals with correct precision, by passing them as strings. Then everything works as expected:

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

>>> 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')

#2


0  

Is this what you are looking for?

这是你想要的?

float('{:,.3f}'.format(2.2225))

#3


0  

Here are three solution in this link, I hope this would help you exactly what you want to do. https://gist.github.com/jackiekazil/6201722

以下是此链接中的三个解决方案,我希望这可以帮助您准确地完成您想要做的事情。 https://gist.github.com/jackiekazil/6201722

from decimal import Decimal

# First we take a float and convert it to a decimal
x = Decimal(16.0/7)

# Then we round it to 2 places
output = round(x,2)
# Output to screen
print output

#1


7  

The problem is that Decimal(1.2225) is not what you expect it to be:

问题是Decimal(1.2225)不是你所期望的那样:

>>> Decimal(1.2225)
Decimal('1.2224999999999999200639422269887290894985198974609375')

You are using a float to the create the decimal, but that float is already too imprecise for your use case. As you can see, it’s actually a 1.222499 so it is smaller than 1.2225 and as such would correctly round down.

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

In order to fix that, you need to create decimals with correct precision, by passing them as strings. Then everything works as expected:

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

>>> 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')

#2


0  

Is this what you are looking for?

这是你想要的?

float('{:,.3f}'.format(2.2225))

#3


0  

Here are three solution in this link, I hope this would help you exactly what you want to do. https://gist.github.com/jackiekazil/6201722

以下是此链接中的三个解决方案,我希望这可以帮助您准确地完成您想要做的事情。 https://gist.github.com/jackiekazil/6201722

from decimal import Decimal

# First we take a float and convert it to a decimal
x = Decimal(16.0/7)

# Then we round it to 2 places
output = round(x,2)
# Output to screen
print output