Search code examples
pythonrounding

Why does Python round 3.15 down to 3.1


According to Python's Banker's rounding way of rounding, it should round to an even number if it is .5 and would therefore go to 3.2. It is the same for 0.15, 1.15, 2.15 and 3.15 but 4.15 is as I would expect. Why does it do this, as banker's rounding (rounding to the even value) should mean it rounds to .2 instead of .1.

What happened:

>>> print(round(3.15, 1))
3.1

What I expected:

>>> print(round(3.15, 1))
3.2

Solution

  • This is due to floating point issues, None of the values represented by those float literals can be represented exactly in binary, so they are always slightly above or below what you wrote in the source code:

    import decimal
    
    floats = 0.15, 1.15, 2.15, 3.15, 4.15
    for f in floats:
        print(decimal.Decimal(f))
    

    You see:

    0.1499999999999999944488848768742172978818416595458984375
    1.149999999999999911182158029987476766109466552734375
    2.149999999999999911182158029987476766109466552734375
    3.149999999999999911182158029987476766109466552734375
    4.1500000000000003552713678800500929355621337890625
    

    Note, if we use the exact values:

    decimals = list(map(decimal.Decimal, ['0.15', '1.15', '2.15', '3.15', '4.15']))
    for d in decimals:
        print(d, round(d, 1))
    

    We get what you would expect:

    0.15 0.2
    1.15 1.2
    2.15 2.2
    3.15 3.2
    4.15 4.2
    

    We can construct floats that we know are representable exactly in binary (they are powers of 2):

    exact = [(n, 2**(-n)) for n in range(1, 6)]
    for exponent, f in exact:
        print(decimal.Decimal(f), round(f, exponent-1))
    

    And we see now the float objects "work":

    0.5 0.0
    0.25 0.2
    0.125 0.12
    0.0625 0.062
    0.03125 0.0312