This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

Title: Rounding properly
Type: behavior Stage: resolved
Components: Documentation Versions: Python 2.7
Status: closed Resolution: out of date
Dependencies: Superseder:
Assigned To: docs@python Nosy List: docs@python, fenofonts, geoffreyspear, jeroen1225, mark.dickinson, rhettinger, serhiy.storchaka
Priority: normal Keywords:

Created on 2014-07-07 10:35 by jeroen1225, last changed 2022-04-11 14:58 by admin. This issue is now closed.

File name Uploaded Description Edit jeroen1225, 2014-07-07 10:35 Rounding
Messages (7)
msg222444 - (view) Author: Jeroen de Jong (jeroen1225) Date: 2014-07-07 10:35
I ma trying to find a way to round correctly. So far I get unexpected results for some values.
msg222452 - (view) Author: Mark Dickinson (mark.dickinson) * (Python committer) Date: 2014-07-07 12:00
This is working as designed, though admittedly the cause of the unexpected results is non-obvious.

In Python 2, there's no way to implement `round` for a general type:  instead, the `round` function converts its *input* to a Python (binary) float, and then rounds the resulting value.  So you're effectively doing:

>>> from decimal import Decimal
>>> round(float(Decimal('167.75')), 1)
>>> round(float(Decimal('167.85')), 1)
>>> round(float(Decimal('167.95')), 1)

And the results above are explainable in terms of rounding the corresponding floating-point value:  the closest exactly representable binary float to 167.85 is 167.849999999999994315658113919198513031005859375, which is a touch less than the halfway mark, so rounds down.  Similarly, the closest exactly representable float to 167.95 is 167.94999999999998863131622783839702606201171875, which again rounds down.  167.75 is already exactly representable as a float, so there you get the expected result.

In Python 3, `round` rounds the Decimal object directly without converting to float first, so you shouldn't see the above problems.  In Python 2, you'll need to stick to your quantize approach.
msg222453 - (view) Author: Mark Dickinson (mark.dickinson) * (Python committer) Date: 2014-07-07 12:01
There may be an opportunity for a documentation improvement here: it would be helpful if the Python 2.7 documentation for the "round" function explained that its input is converted to float.
msg222543 - (view) Author: Raymond Hettinger (rhettinger) * (Python committer) Date: 2014-07-08 04:47
FWIW, the FAQ in the decimal docs shows how to round Decimal objects using the quantize() method:

Unfortunately, only it Python 3 does the one-obvious-way-to-do-it work.
msg226581 - (view) Author: Robert (fenofonts) Date: 2014-09-08 13:47
I'm not sure if this is related or not, but on 3.4.1 I get the following: 

>>> print(round(float(3/2)))
2 (as expected)
>>> print(round(float(5/2)))
2 (expected 3, as float should round .5 up)
msg226583 - (view) Author: Geoffrey Spear (geoffreyspear) * Date: 2014-09-08 15:09

That is not related. Python 3's round() function, as documented, rounds halves to the even choice; what you describe is the expected behavior.
msg370471 - (view) Author: Serhiy Storchaka (serhiy.storchaka) * (Python committer) Date: 2020-05-31 14:47
Python 2.7 is no longer supported.
Date User Action Args
2022-04-11 14:58:05adminsetgithub: 66128
2020-05-31 14:47:20serhiy.storchakasetstatus: open -> closed

nosy: + serhiy.storchaka
messages: + msg370471

resolution: out of date
stage: resolved
2014-10-14 17:01:02skrahsetnosy: - skrah
2014-09-08 15:09:11geoffreyspearsetnosy: + geoffreyspear
messages: + msg226583
2014-09-08 13:47:33fenofontssetnosy: + fenofonts
messages: + msg226581
2014-07-08 04:47:43rhettingersetnosy: + rhettinger
messages: + msg222543
2014-07-07 12:01:25mark.dickinsonsetnosy: + docs@python
messages: + msg222453

assignee: docs@python
components: + Documentation, - Windows
2014-07-07 12:00:27mark.dickinsonsetmessages: + msg222452
2014-07-07 10:39:09ezio.melottisetnosy: + mark.dickinson, skrah
2014-07-07 10:35:06jeroen1225create