4

I'm posting this with what I think is the answer because I couldn't find a similar question-answer here.

I expected pandas round method to round 0.5 up to 1.

>>> import pandas as pd
>>> pd.Series([0.5, 1.5, 2.5, 3.5, 4.5]).round()
0    0.0
1    2.0
2    2.0
3    4.0
4    4.0
dtype: float64

Even more strange: Python's round method has different behaviour in Python 2.7 and 3.6:

Python 2.7:

>>> [round(x) for x in [0.5, 1.5, 2.5, 3.5, 4.5]]
[1.0, 2.0, 3.0, 4.0, 5.0]

Python 3.6:

>>> [round(x) for x in [0.5, 1.5, 2.5, 3.5, 4.5]]
[0, 2, 2, 4, 4]

Is this something to do with floating-point representation or my platform (Mac OS X)?

Bill
  • 10,323
  • 10
  • 62
  • 85
  • Thanks @root. For whatever reason that existing question did not come up when I searched this issue - or even in the list of similar posts when I was writing the question. – Bill Oct 08 '18 at 19:23

2 Answers2

4

I believe in thisc ase it is actually intended behaviour in python, and not a floating point problem. Looking at the documentation:

if two multiples are equally close, rounding is done toward the even choice (so, for example, both round(0.5) and round(-0.5) are 0, and round(1.5) is 2)

sacuL
  • 49,704
  • 8
  • 81
  • 106
  • Oh, I see. So it's not floating point representation. Is there a reason why it is rounded to the nearest even number? And not say towards zero or "upwards" away from zero (which I always thought it was supposed to be)? – Bill Oct 08 '18 at 19:21
  • 1
    @Bill For the reasons, read the dupe. – wim Oct 08 '18 at 19:22
  • 1
    What is dupe? I read the Python documentation again and I couldn't find the reason. But I found an explanation [here](https://mathematica.stackexchange.com/a/2120): "I think the reason is to prevent biasing numbers on average upward or downward." – Bill Oct 08 '18 at 19:29
  • @Bill, for future reference, "dupe" is short for "duplicate". – sacuL Oct 08 '18 at 21:58
0

This is indeed due to floating point arithmetic as described in the Python 3 documentation for round() in where it states:

The behavior of round() for floats can be surprising: for example, round(2.675, 2) gives 2.67 instead of the expected 2.68. This is not a bug: it’s a result of the fact that most decimal fractions can’t be represented exactly as a float.

Bill
  • 10,323
  • 10
  • 62
  • 85
  • 2
    This misses why 0.5 rounds down to 0, but 1.5 rounds up to 2. Both decimals, having sufficiently small magnitudes and with powers of 2 as denominators, have exact representations in floating point. – chepner Oct 08 '18 at 19:16
  • @chepner The [Python docs](https://docs.python.org/3/library/functions.html#round) contradict themselves. They say that the rounding will be toward the nearest even number...but then they say that, well, sometimes it won't be--but that it's not a bug. – Carl Parker Jul 22 '20 at 03:45
  • The problem is that 2.675 isn't 2675/1000; it's a number closer to 267/100 and 268/100. Rounding toward the nearest even number *only* applies when the value to be rounded is *exactly* halfway between the two options. – chepner Jul 22 '20 at 12:34