round() doesn't seem to be rounding properly

247,388

Solution 1

I can't help the way it's stored, but at least formatting works correctly:

'%.1f' % round(n, 1) # Gives you '5.6'

Solution 2

Formatting works correctly even without having to round:

"%.1f" % n

Solution 3

If you use the Decimal module you can approximate without the use of the 'round' function. Here is what I've been using for rounding especially when writing monetary applications:

from decimal import Decimal, ROUND_UP

Decimal(str(16.2)).quantize(Decimal('.01'), rounding=ROUND_UP)

This will return a Decimal Number which is 16.20.

Solution 4

round(5.59, 1) is working fine. The problem is that 5.6 cannot be represented exactly in binary floating point.

>>> 5.6
5.5999999999999996
>>> 

As Vinko says, you can use string formatting to do rounding for display.

Python has a module for decimal arithmetic if you need that.

Solution 5

You get '5.6' if you do str(round(n, 1)) instead of just round(n, 1).

Share:
247,388
swilliams
Author by

swilliams

I enjoy Programming, Photography, Writing, Cooking, Running, and capitalizing the wrong letters in sentences.

Updated on December 30, 2021

Comments

  • swilliams
    swilliams over 2 years

    The documentation for the round() function states that you pass it a number, and the positions past the decimal to round. Thus it should do this:

    n = 5.59
    round(n, 1) # 5.6
    

    But, in actuality, good old floating point weirdness creeps in and you get:

    5.5999999999999996
    

    For the purposes of UI, I need to display 5.6. I poked around the Internet and found some documentation that this is dependent on my implementation of Python. Unfortunately, this occurs on both my Windows dev machine and each Linux server I've tried. See here also.

    Short of creating my own round library, is there any way around this?

  • whereswalden
    whereswalden almost 10 years
    According to the docs, this style of string formatting will eventually go away. The new-style format would be "{:.1f}".format(n)
  • schlamar
    schlamar almost 9 years
    Does not round correctly: '%.5f' % 0.988625 gives 0.98862
  • Liza
    Liza almost 9 years
    i tried print '%.2f' % 655.665 but it returns 655.66, it should be 655.67
  • Boti
    Boti almost 9 years
    @Kyrie see stackoverflow.com/questions/9301690/…. Floating point inaccuracy is to blame here -- "5.665 -> 5.67" but "15.665 -> 15.66". Use decimals if you need exact precision.
  • Liza
    Liza almost 9 years
    this is working after searching :) from decimal import Decimal, ROUND_HALF_UP, ROUND_HALF_DOWN # use in rounding floating numbers Decimal(str(655.665)).quantize(Decimal('1.11'), rounding=ROUND_HALF_UP) # Issues and Limitations in floating points
  • Vinko Vrsalovic
    Vinko Vrsalovic almost 9 years
    @schlamar: That's round()'s behavior as well: round(0.988625,5) also gives 0.98862. round(0.988626,5) as well as "%.5f" % 0.988626 give 0.98863
  • Cecil Curry
    Cecil Curry over 8 years
    This is the canonical answer – where accuracy matters, anyway, which is pretty much everywhere. Sure: it's a bit verbose. But throw that sucker in a helper function and you're good to format and go.
  • Dion
    Dion about 8 years
    unfortunately "%.2f" % 2.675 will return 2.67 - which might be an unexpected answer for those using this method and expecting 2.68
  • Michael Scott Asato Cuthbert
    Michael Scott Asato Cuthbert over 7 years
    That would only work if the rounding were consistently off from the round number by epsilon. If epsilon = .000001 then round(1.0/5.0, 1) + epsilon would take the precise representation 0.2 and make it 0.00001. Equally bad problems would happen if the epsilon were inside the round function.
  • Ami
    Ami over 7 years
    This is no l longer a problem with either Python 2.7 or Python 3.5
  • Simon MᶜKenzie
    Simon MᶜKenzie about 6 years
    What you're talking about is "bankers' rounding", one of many different ways to perform rounding.
  • Stephen Blair
    Stephen Blair almost 6 years
    If you get this error NameError: global name 'ROUND_UP' is not defined you need to import your rounding function: from decimal import Decimal, ROUND_UP. Other rounding functions
  • YvesgereY
    YvesgereY over 4 years
    Your example seems still dangerous: you rely on the rounding provided by str().