[python] Round number to nearest integer

I've been trying to round long float numbers like:

32.268907563;
32.268907563;
31.2396694215;
33.6206896552;
...

With no success so far. I tried math.ceil(x), math.floor(x) (although that would round up or down, which is not what I'm looking for) and round(x) which didn't work either (still float numbers).

What could I do?

EDIT: CODE:

for i in widthRange:
    for j in heightRange:
        r, g, b = rgb_im.getpixel((i, j))
        h, s, v = colorsys.rgb_to_hsv(r/255.0, g/255.0, b/255.0)
        h = h * 360
        int(round(h))
        print(h)

This question is related to python

The answer is


Isn't just Python doing round half to even, as prescribed by IEEE 754?

Be careful redefining, or using "non-standard" rounding…

(See also https://stackoverflow.com/a/33019948/109839)


If you need (for example) a two digit approximation for A, then int(A*100+0.5)/100.0 will do what you are looking for.

If you need three digit approximation multiply and divide by 1000 and so on.


round(value,significantDigit) is the ordinary solution, however this does not operate as one would expect from a math perspective when round values ending in 5. If the 5 is in the digit just after the one you're rounded to, these values are only sometimes rounded up as expected (i.e. 8.005 rounding to two decimal digits gives 8.01). For certain values due to the quirks of floating point math, they are rounded down instead!

i.e.

>>> round(1.0005,3)
1.0
>>> round(2.0005,3)
2.001
>>> round(3.0005,3)
3.001
>>> round(4.0005,3)
4.0
>>> round(1.005,2)
1.0
>>> round(5.005,2)
5.0
>>> round(6.005,2)
6.0
>>> round(7.005,2)
7.0
>>> round(3.005,2)
3.0
>>> round(8.005,2)
8.01

Weird.

Assuming your intent is to do the traditional rounding for statistics in the sciences, this is a handy wrapper to get the round function working as expected needing to import extra stuff like Decimal.

>>> round(0.075,2)

0.07

>>> round(0.075+10**(-2*5),2)

0.08

Aha! So based on this we can make a function...

def roundTraditional(val,digits):
   return round(val+10**(-len(str(val))-1), digits)

Basically this adds a value guaranteed to be smaller than the least given digit of the string you're trying to use round on. By adding that small quantity it preserve's round's behavior in most cases, while now ensuring if the digit inferior to the one being rounded to is 5 it rounds up, and if it is 4 it rounds down.

The approach of using 10**(-len(val)-1) was deliberate, as it the largest small number you can add to force the shift, while also ensuring that the value you add never changes the rounding even if the decimal . is missing. I could use just 10**(-len(val)) with a condiditional if (val>1) to subtract 1 more... but it's simpler to just always subtract the 1 as that won't change much the applicable range of decimal numbers this workaround can properly handle. This approach will fail if your values reaches the limits of the type, this will fail, but for nearly the entire range of valid decimal values it should work.

You can also use the decimal library to accomplish this, but the wrapper I propose is simpler and may be preferred in some cases.


Edit: Thanks Blckknght for pointing out that the 5 fringe case occurs only for certain values. Also an earlier version of this answer wasn't explicit enough that the odd rounding behavior occurs only when the digit immediately inferior to the digit you're rounding to has a 5.


Your solution is calling round without specifying the second argument (number of decimal places)

>>> round(0.44)
0
>>> round(0.64)
1

which is a much better result than

>>> int(round(0.44, 2))
0
>>> int(round(0.64, 2))
0

From the Python documentation at https://docs.python.org/3/library/functions.html#round

round(number[, ndigits])

Return number rounded to ndigits precision after the decimal point. If ndigits is omitted or is None, it returns the nearest integer to its input.

Note

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. See Floating Point Arithmetic: Issues and Limitations for more information.


This one is tricky, to be honest. There are many simple ways to do this nevertheless. Using math.ceil(), round(), and math.floor(), you can get a integer by using for example:

n = int(round(n))

If before we used this function n = 5.23, we would get returned 5. If you wanted to round to different place values, you could use this function:

def Round(n,k):
  point = '%0.' + str(k) + 'f'
  if k == 0:
    return int(point % n)
  else:
    return float(point % n)

If we used n (5.23) again, round it to the nearest tenth, and print the answer to the console, our code would be:

Round(5.23,1)

Which would return 5.2. Finally, if you wanted to round something to the nearest, let's say, 1.2, you can use the code:

def Round(n,k):
    return k * round(n/k)

If we wanted n to be rounded to 1.2, our code would be:

print(Round(n,1.2))

and our result:

4.8

Thank you! If you have any questions, please add a comment. :) (Happy Holidays!)


You can also use numpy assuming if you are using python3.x here is an example

import numpy as np
x = 2.3
print(np.rint(x))
>>> 2.0

For positives, try

int(x + 0.5)

To make it work for negatives too, try

int(x + (0.5 if x > 0 else -0.5))

int() works like a floor function and hence you can exploit this property. This is definitely the fastest way.


I use and may advise the following solution (python3.6):

y = int(x + (x % (1 if x >= 0 else -1)))

It works fine for half-numbers (positives and negatives) and works even faster than int(round(x)):

round_methods = [lambda x: int(round(x)), 
                 lambda x: int(x + (x % (1 if x >= 0 else -1))),
                 lambda x: np.rint(x).astype(int),
                 lambda x: int(proper_round(x))]

for rm in round_methods:
    %timeit rm(112.5)
Out:
201 ns ± 3.96 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
159 ns ± 0.646 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
925 ns ± 7.66 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
1.18 µs ± 8.66 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

for rm in round_methods:
    print(rm(112.4), rm(112.5), rm(112.6))
    print(rm(-12.4), rm(-12.5), rm(-12.6))
    print('=' * 11)

Out:
112 112 113
-12 -12 -13
===========
112 113 113
-12 -13 -13
===========
112 112 113
-12 -12 -13
===========
112 113 113
-12 -13 -13
===========

Use round(x, y). It will round up your number up to your desired decimal place.

For example:

>>> round(32.268907563, 3)
32.269

For this purpose I would suggest just do the following thing -

int(round(x))

This will give you nearest integer.

Hope this helps!!


Some thing like this should also work

import numpy as np    

def proper_round(a):
    '''
    given any real number 'a' returns an integer closest to 'a'
    '''
    a_ceil = np.ceil(a)
    a_floor = np.floor(a)
    if np.abs(a_ceil - a) < np.abs(a_floor - a):
        return int(a_ceil)
    else:
        return int(a_floor)