round() doesn't seem to be rounding properly
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)
.
swilliams
I enjoy Programming, Photography, Writing, Cooking, Running, and capitalizing the wrong letters in sentences.
Updated on December 30, 2021Comments
-
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 almost 10 yearsAccording to the docs, this style of string formatting will eventually go away. The new-style format would be
"{:.1f}".format(n)
-
schlamar almost 9 yearsDoes not round correctly:
'%.5f' % 0.988625
gives0.98862
-
Liza almost 9 yearsi tried
print '%.2f' % 655.665
but it returns655.66
, it should be655.67
-
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 almost 9 yearsthis is working after searching :)
from decimal import Decimal, ROUND_HALF_UP, ROUND_HALF_DOWN
# use in rounding floating numbersDecimal(str(655.665)).quantize(Decimal('1.11'), rounding=ROUND_HALF_UP)
# Issues and Limitations in floating points -
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 over 8 yearsThis 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 about 8 yearsunfortunately "%.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 over 7 yearsThat would only work if the rounding were consistently off from the round number by epsilon. If
epsilon = .000001
thenround(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 over 7 yearsThis is no l longer a problem with either Python 2.7 or Python 3.5
-
Simon MᶜKenzie about 6 yearsWhat you're talking about is "bankers' rounding", one of many different ways to perform rounding.
-
Stephen Blair almost 6 yearsIf 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 over 4 yearsYour example seems still dangerous: you rely on the rounding provided by str().