So I have a list of floats that I am manipulating in a function. On the output of the function, I would like to round this to the nearest 100. So I would like to rounding to be like this: 157395.85 ----> 157400.00.
Here is an example of the code I wrote:
x = 157395.85
print(round(x, 4))
This did not run correctly. Another issue I noticed was that if the float had a zero at the last digit after the decimal, the zero was not listed. What I mean is that 50000.50 is stored as 50000.5.
Any help would be great!
Edit: To all that have commented, your solutions were amazing thank you so much! I've upvoted all your comments.
Rounding is typically done on floating point numbers, and here there are three basic functions you should know: round (rounds to the nearest integer), math.floor (always rounds down), and math.ceil (always rounds up).
You ask about integers and rounding up to hundreds, but we can still use math.ceil as long as your numbers smaller than 253. To use math.ceil, we just divide by 100 first, round up, and multiply with 100 afterwards:
Copy>>> import math
>>> def roundup(x):
... return int(math.ceil(x / 100.0)) * 100
...
>>> roundup(100)
100
>>> roundup(101)
200
Dividing by 100 first and multiply with 100 afterwards "shifts" two decimal places to the right and left so that math.ceil works on the hundreds. You could use 10**n instead of 100 if you want to round to tens (n = 1), thousands (n = 3), etc.
An alternative way to do this is to avoid floating point numbers (they have limited precision) and instead use integers only. Integers have arbitrary precision in Python, so this lets you round numbers of any size. The rule for rounding is simple: find the remainder after division with 100, and add 100 minus this remainder if it's non-zero:
Copy>>> def roundup(x):
... return x if x % 100 == 0 else x + 100 - x % 100
This works for numbers of any size:
Copy>>> roundup(100)
100
>>> roundup(130)
200
>>> roundup(1234567891234567891)
1234567891234567900L
I did a mini-benchmark of the two solutions:
Copy$ python -m timeit -s 'import math' -s 'x = 130' 'int(math.ceil(x/100.0)) * 100'
1000000 loops, best of 3: 0.364 usec per loop
$ python -m timeit -s 'x = 130' 'x if x % 100 == 0 else x + 100 - x % 100'
10000000 loops, best of 3: 0.162 usec per loop
The pure integer solution is faster by a factor of two compared to the math.ceil solution.
Thomas proposed an integer based solution that is identical to the one I have above, except that it uses a trick by multiplying Boolean values. It is interesting to see that there is no speed advantage of writing the code this way:
Copy$ python -m timeit -s 'x = 130' 'x + 100*(x%100>0) - x%100'
10000000 loops, best of 3: 0.167 usec per loop
As a final remark, let me also note, that if you had wanted to round 101โ149 to 100 and round 150โ199 to 200, e.g., round to the nearest hundred, then the built-in round function can do that for you:
Copy>>> int(round(130, -2))
100
>>> int(round(170, -2))
200
This is a late answer, but there's a simple solution that combines the best aspects of the existing answers: the next multiple of 100 up from x is x - x % -100 (or if you prefer, x + (-x) % 100).
Copy>>> x = 130
>>> x -= x % -100 # Round x up to next multiple of 100.
>>> x
200
This is fast and simple, gives correct results for any integer x (like John Machin's answer) and also gives reasonable-ish results (modulo the usual caveats about floating-point representation) if x is a float (like Martin Geisler's answer).
Copy>>> x = 0.1
>>> x -= x % -100
>>> x
100.0
Videos
You need divide by 100, convert to int and last multiple by 100:
df['new_values'] = (df['old_values'] / 100).astype(int) *100
Same as:
df['new_values'] = (df['old_values'] / 100).apply(np.floor).astype(int) *100
Sample:
df = pd.DataFrame({'old_values':[8450, 8470, 343, 573, 34543, 23999]})
df['new_values'] = (df['old_values'] / 100).astype(int) *100
print (df)
old_values new_values
0 8450 8400
1 8470 8400
2 343 300
3 573 500
4 34543 34500
5 23999 23900
EDIT:
df = pd.DataFrame({'old_values':[3, 6, 89, 573, 34, 23]})
#show output of first divide for verifying output
df['new_values1'] = (10000/df['old_values'])
df['new_values'] = (10000/df['old_values']).div(100).astype(int).mul(100)
print (df)
old_values new_values1 new_values
0 3 3333.333333 3300
1 6 1666.666667 1600
2 89 112.359551 100
3 573 17.452007 0
4 34 294.117647 200
5 23 434.782609 400
Borrowing @jezrael's sample dataframe
df = pd.DataFrame({'old_values':[8450, 8470, 343, 573, 34543, 23999]})
Use floordiv or //
df // 100 * 100
old_values
0 8400
1 8400
2 300
3 500
4 34500
5 23900
def round_down(num, divisor):
return num - (num%divisor)
In [2]: round_down(19,10)
Out[2]: 10
In [3]: round_down(19,5)
Out[3]: 15
In [4]: round_down(10,10)
Out[4]: 10
This probably isn't the most efficient solution, but
def round_down(m, n):
return m // n * n
is pretty simple.
You may use either of these three ways (there may exist many more ways):
import math
print(math.floor(5398 / 100.00) * 100)
Output is 5300 as expected.
rounded = int(5398 / 100) * 100
print(rounded)
Still the output is 5300.
import numpy
print(int(numpy.floor(5398 / 100.0) * 100))
The output is still 5300 :)
Have Fun :)
You can do that by taking the integer part of the number divided by 100 and then multiplying by 100:
rounded = int(your_number / 100) * 100
A general purpose solution, this allows rounding to an arbitrary resolution (well, other than zero of course, but a resolution of zero makes little sense (a)). For your case, you just need to provide 0.02 as the resolution, though other values are possible, as shown in the test cases.
# This is the function you want.
def roundPartial (value, resolution):
return round (value / resolution) * resolution
# All these are just test cases, the first two being your own test data.
print "Rounding to fiftieths"
print roundPartial (0.405, 0.02)
print roundPartial (0.412, 0.02)
print "Rounding to quarters"
print roundPartial (1.38, 0.25)
print roundPartial (1.12, 0.25)
print roundPartial (9.24, 0.25)
print roundPartial (7.76, 0.25)
print "Rounding to hundreds"
print roundPartial (987654321, 100)
This outputs:
Rounding to fiftieths
0.4
0.42
Rounding to quarters
1.5
1.0
9.25
7.75
Rounding to hundreds
987654300.0
(a) If you have the particular personality disorder that requires you to handle this possibility, just be aware that you're after the closest number that is a multiple of your desired resolution. Since the closest number to N (for any N) that is a multiple of 0 is always 0, you could modify the function as follows:
def roundPartial (value, resolution):
if resolution == 0:
return 0
return round (value / resolution) * resolution
Alternatively, you could simply promise yourself not to pass zero as a resolution :-)
A small fix to the earlier solution:
def roundPartial (value, resolution):
return round (float(value) / resolution) * resolution
Earlier
roundPartial(19, 10) = 10.0
With fix
roundPartial(19, 10) = 20.0
round does take negative ndigits parameter!
>>> round(46,-1)
50
may solve your case.
You can use math.ceil() to round up, and then multiply by 10
Python 2
import math
def roundup(x):
return int(math.ceil(x / 10.0)) * 10
Python 3 (the only difference is you no longer need to cast the result as an int)
import math
def roundup(x):
return math.ceil(x / 10.0) * 10
To use just do
>>roundup(45)
50