Round up to Second Decimal Place in Python

PythonRounding

Python Problem Overview


How can I round up a number to the second decimal place in python? For example:

0.022499999999999999

Should round up to 0.03

0.1111111111111000

Should round up to 0.12

If there is any value in the third decimal place, I want it to always round up leaving me 2 values behind the decimal point.

Python Solutions


Solution 1 - Python

Python includes the round() function which lets you specify the number of digits you want. From the documentation:

> round(x[, n]) > >Return the floating point value x rounded to n digits after the decimal point. If n is omitted, it defaults to zero. The result is a floating point number. Values are rounded to the closest multiple of 10 to the power minus n; if two multiples are equally close, rounding is done away from 0 (so. for example, round(0.5) is 1.0 and round(-0.5) is -1.0).

So you would want to use round(x, 2) to do normal rounding. To ensure that the number is always rounded up you would need to use the ceil(x) function. Similarly, to round down use floor(x).

Solution 2 - Python

from math import ceil

num = 0.1111111111000
num = ceil(num * 100) / 100.0

See:
math.ceil documentation
round documentation - You'll probably want to check this out anyway for future reference

Solution 3 - Python

x = math.ceil(x * 100.0) / 100.0

Solution 4 - Python

Updated answer:
The problem with my original answer, as pointed out in the comments by @jpm, is the behavior at the boundaries. Python 3 makes this even more difficult since it uses "bankers" rounding instead of "old school" rounding. However, in looking into this issue I discovered an even better solution using the decimal library.

import decimal

def round_up(x, place=0):
    context = decimal.getcontext()
    # get the original setting so we can put it back when we're done
    original_rounding = context.rounding
    # change context to act like ceil()
    context.rounding = decimal.ROUND_CEILING
    
    rounded = round(decimal.Decimal(str(x)), place)
    context.rounding = original_rounding
    return float(rounded)

Or if you really just want a one-liner:

import decimal
decimal.getcontext().rounding = decimal.ROUND_CEILING

# here's the one-liner
float(round(decimal.Decimal(str(0.1111)), ndigits=2))
>> 0.12

# Note: this only affects the rounding of `Decimal`
round(0.1111, ndigits=2)
>> 0.11

Here are some examples:

round_up(0.022499999999999999, 2)
>> 0.03
round_up(0.1111111111111000, 2)
>> 0.12
round_up(0.1111111111111000, 3)
>> 0.112

round_up(3.4)
>> 4.0

# @jpm - boundaries do what we want
round_up(0.1, 2)
>> 0.1
round_up(1.1, 2)
>> 1.1

# Note: this still rounds toward `inf`, not "away from zero"
round_up(2.049, 2)
>> 2.05
round_up(-2.0449, 2)
>> -2.04

We can use it to round to the left of the decimal as well:

round_up(11, -1)
>> 20

We don't multiply by 10, thereby avoiding the overflow mentioned in this answer.

round_up(1.01e308, -307)
>> 1.1e+308

Original Answer (Not recommended):
This depends on the behavior you want when considering positive and negative numbers, but if you want something that always rounds to a larger value (e.g. 2.0449 -> 2.05, -2.0449 -> -2.04) then you can do:

round(x + 0.005, 2)

or a little fancier:

def round_up(x, place):
    return round(x + 5 * 10**(-1 * (place + 1)), place)

This also seems to work as follows:

round(144, -1)
# 140
round_up(144, -1)
# 150
round_up(1e308, -307)
# 1.1e308

Solution 5 - Python

Extrapolating from Edwin's answer:

from math import ceil, floor
def float_round(num, places = 0, direction = floor):
    return direction(num * (10**places)) / float(10**places)

To use:

>>> float_round(0.21111, 3, ceil)  #round up
>>> 0.212
>>> float_round(0.21111, 3)        #round down
>>> 0.211
>>> float_round(0.21111, 3, round) #round naturally
>>> 0.211

Solution 6 - Python

Note that the ceil(num * 100) / 100 trick will crash on some degenerate inputs, like 1e308. This may not come up often but I can tell you it just cost me a couple of days. To avoid this, "it would be nice if" ceil() and floor() took a decimal places argument, like round() does... Meanwhile, anyone know a clean alternative that won't crash on inputs like this? I had some hopes for the decimal package but it seems to die too:

>>> from math import ceil
>>> from decimal import Decimal, ROUND_DOWN, ROUND_UP
>>> num = 0.1111111111000
>>> ceil(num * 100) / 100
0.12
>>> float(Decimal(num).quantize(Decimal('.01'), rounding=ROUND_UP))
0.12
>>> num = 1e308
>>> ceil(num * 100) / 100
Traceback (most recent call last):
  File "<string>", line 301, in runcode
  File "<interactive input>", line 1, in <module>
OverflowError: cannot convert float infinity to integer
>>> float(Decimal(num).quantize(Decimal('.01'), rounding=ROUND_UP))
Traceback (most recent call last):
  File "<string>", line 301, in runcode
  File "<interactive input>", line 1, in <module>
decimal.InvalidOperation: [<class 'decimal.InvalidOperation'>]

Of course one might say that crashing is the only sane behavior on such inputs, but I would argue that it's not the rounding but the multiplication that's causing the problem (that's why, eg, 1e306 doesn't crash), and a cleaner implementation of the round-up-nth-place fn would avoid the multiplication hack.

Solution 7 - Python

Here is a more general one-liner that works for any digits:

import math
def ceil(number, digits) -> float: return math.ceil((10.0 ** digits) * number) / (10.0 ** digits)

Example usage:

>>> ceil(1.111111, 2)
1.12

Caveat: as stated by nimeshkiranverma:

>>> ceil(1.11, 2) 
1.12  #Because: 1.11 * 100.0 has value 111.00000000000001

Solution 8 - Python

def round_up(number, ndigits=None):
    # start by just rounding the number, as sometimes this rounds it up
    result = round(number, ndigits if ndigits else 0)
    if result < number:
        # whoops, the number was rounded down instead, so correct for that
        if ndigits:
            # use the type of number provided, e.g. float, decimal, fraction
            Numerical = type(number)
            # add the digit 1 in the correct decimal place
            result += Numerical(10) ** -ndigits
            # may need to be tweaked slightly if the addition was inexact
            result = round(result, ndigits)
        else:
            result += 1 # same as 10 ** -0 for precision of zero digits
    return result

assert round_up(0.022499999999999999, 2) == 0.03
assert round_up(0.1111111111111000, 2) == 0.12

assert round_up(1.11, 2) == 1.11
assert round_up(1e308, 2) == 1e308

Solution 9 - Python

The python round function could be rounding the way not you expected.

You can be more specific about the rounding method by using Decimal.quantize

eg.

from decimal import Decimal, ROUND_HALF_UP
res = Decimal('0.25').quantize(Decimal('0.0'), rounding=ROUND_HALF_UP)
print(res) 
# prints 0.3

More reference:

https://gist.github.com/jackiekazil/6201722

Solution 10 - Python

Here's a simple way to do it that I don't see in the other answers.

To round up to the second decimal place:

>>> n = 0.022499999999999999
>>> 
>>> -(-n//.01) * .01
0.03
>>> 

Other value:

>>> n = 0.1111111111111000
>>> 
>>> -(-n//.01) * .01
0.12
>>> 

With floats there's the occasional value with some minute imprecision, which can be corrected for if you're displaying the values for instance:

>>> n = 10.1111111111111000
>>> 
>>> -(-n//0.01) * 0.01
10.120000000000001
>>> 
>>> f"{-(-n//0.01) * 0.01:.2f}"
'10.12'
>>> 

A simple roundup function with a parameter to specify precision:

>>> roundup = lambda n, p: -(-n//10**-p) * 10**-p
>>> 
>>> # Or if you want to ensure truncation using the f-string method:
>>> roundup = lambda n, p: float(f"{-(-n//10**-p) * 10**-p:.{p}f}")
>>> 
>>> roundup(0.111111111, 2)
0.12
>>> roundup(0.111111111, 3)
0.112

Solution 11 - Python

The round funtion stated does not works for definate integers like : > a=8
> round(a,3)
8.0
> a=8.00
> round(a,3)
8.0
> a=8.000000000000000000000000
> round(a,3)
8.0

but , works for : > r=400/3.0
> r
133.33333333333334
> round(r,3)
133.333

Morever the decimals like 2.675 are rounded as 2.67 not 2.68.
Better use the other method provided above.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionuser1202589View Question on Stackoverflow
Solution 1 - PythonsimchonaView Answer on Stackoverflow
Solution 2 - PythonEdwinView Answer on Stackoverflow
Solution 3 - PythonMark RansomView Answer on Stackoverflow
Solution 4 - Pythonajp619View Answer on Stackoverflow
Solution 5 - PythonPatrick PeriniView Answer on Stackoverflow
Solution 6 - PythonJacob EliosoffView Answer on Stackoverflow
Solution 7 - PythonFerroView Answer on Stackoverflow
Solution 8 - PythonDavid Augusto VillaView Answer on Stackoverflow
Solution 9 - PythonJames LinView Answer on Stackoverflow
Solution 10 - PythonToddView Answer on Stackoverflow
Solution 11 - PythonShikharView Answer on Stackoverflow