how to round to higher 10's place in python - python

I have a bunch of floats and I want to round them up to the next highest multiple of 10.
For example:
10.2 should be 20
10.0 should be 10
16.7 should be 20
94.9 should be 100
I only need it to go from the range 0-100. I tried math.ceil() but that only rounds up to the nearest integer.
Thanks in advance.

from math import ceil
def ceil_to_tens(x):
return int(ceil(x / 10.0)) * 10
Edit: okay, now that I have an undeserved "Nice answer" badge for this answer, I think owe the community with a proper solution using the decimal module that does not suffer from these problems :) Thanks to Jeff for pointing this out. So, a solution using decimal works as follows:
from decimal import Decimal, ROUND_UP
def ceil_to_tens_decimal(x):
return (Decimal(x) / 10).quantize(1, rounding=ROUND_UP) * 10
Of course the above code requires x to be an integer, a string or a Decimal object - floats won't work as that would defeat the whole purpose of using the decimal module.
It's a pity that Decimal.quantize does not work properly with numbers larger than 1, it would have saved the division-multiplication trick.

>>> x = 16.7
>>> int( 10 * math.ceil(x/10.0))

The answers here are fraught with peril. For example 11*1.1 - 2.1 = 10.0, right? But wait:
>>> x = 11*1.1 - 2.1
>>> int(ceil(x / 10.0)) * 10
20
>>> x
10.000000000000002
>>>
You could try this
int(ceil(round(x, 12) / 10.0)) * 10
But choosing the number of decimal places to round to is really difficult as it is hard to predict how floating point noise accumulates. If it is really important to get this right all of the time, then you need to use fixed point arithmetic or Decimal.

If you're looking for another solution that doesn't involve float division, here's one that uses the modulus:
def ceil_to_tens_mod(x):
tmp = int(ceil(x))
mod10 = tmp % 10
return tmp - mod10 + (10 if mod10 else 0)
There's probably some way to simplify it, but there you go.

Related

How to round 0.055 to 0.06 in Python?

Result of a simple division -34.11/2 returns -17.055 Is there a python function that would return round up decimal? I am expecting to see -17.06
And yes I checked these answers, but neither can answer this question:
Round up to Second Decimal Place in Python
How to round to nearest decimal in Python
Increment a Python floating point value by the smallest possible amount
Python round to nearest 0.25
Any help would be greatly appreciated.
Thanks!
This is a floating point limitation; get around it by using decimal.Decimal.
>>> from decimal import Decimal
>>> Decimal(-34.11/2) # See? Not quite the value you thought.
Decimal('-17.05499999999999971578290569595992565155029296875')
>>> Decimal(-34.11) / Decimal(2) # This doesn't quite work either, because -34.11 is already a little bit off.
Decimal('-17.05499999999999971578290570')
>>> Decimal("-34.11") / Decimal("2")
Decimal('-17.055')
>>> round(Decimal("-34.11") / Decimal("2"), 2)
Decimal('-17.06')

About python's round function [duplicate]

I am using python 2.7, and the code I have is:
a = 10.5 * 22.34 / 2.0
print "%.2f" % a
and the result I expect is 117.29, but it shows 117.28. How to solve the problem?
If Python is using a 64-bit IEEE-754 binary floating point type, then the exact value it's using will be
117.284999999999996589394868351519107818603515625
... and that's obviously lower than the midpoint between 117.28 and 117.29. It's possible that that's what's going on.
Another option is that Python is using Banker's Rounding.
If the exact decimal values matter to you, you might want to consider using decimal instead.
Mr. Skeet has the correct answer, below is an example of how to use the decimal module to which he refers:
import decimal
a = decimal.Decimal('117.285')
rounded = a.quantize(decimal.Decimal('.01'), rounding=decimal.ROUND_HALF_UP)
print rounded
# 117.29
repr(rounded)
# "Decimal('117.29')"
If you want a simple solution and don't care about performance, you could use a function like this to convert to integer, round, and convert back to float:
def round_exact(number, decimal_places=0):
"""Round the number to the given number of decimal places by converting to
and from integers to avoid floating point error."""
factor = 10**(decimal_places + 1)
rounded_int = int(number * factor)
if rounded_int % 10 >= 5:
# Round up
return (int(rounded_int//10) + 1) / float(factor//10)
# Round down
return int(rounded_int//10) / float(factor//10)

Round python decimal to nearest 0.05

I'm trying to round money numbers in Decimal to the nearest 0.05. Right now, I'm doing this:
def round_down(amount):
amount *= 100
amount = (amount - amount % 5) / Decimal(100)
return Decimal(amount)
def round_up(amount):
amount = int(math.ceil(float(100 * amount) / 5)) * 5 / Decimal(100)
return Decimal(amount)
Is there any way I can do this more elegantly without dealing with floats using python Decimals (using quantize perhaps)?
With floats, simply use round(x * 2, 1) / 2. This doesn't give control over the rounding direction, though.
Using Decimal.quantize you also get complete control over the type and direction of rounding (Python 3.5.1):
>>> from decimal import Decimal, ROUND_UP
>>> x = Decimal("3.426")
>>> (x * 2).quantize(Decimal('.1'), rounding=ROUND_UP) / 2
Decimal('3.45')
>>> x = Decimal("3.456")
>>> (x * 2).quantize(Decimal('.1'), rounding=ROUND_UP) / 2
Decimal('3.5')
A more generic solution for any rounding base.
from decimal import ROUND_DOWN
def round_decimal(decimal_number, base=1, rounding=ROUND_DOWN):
"""
Round decimal number to the nearest base
:param decimal_number: decimal number to round to the nearest base
:type decimal_number: Decimal
:param base: rounding base, e.g. 5, Decimal('0.05')
:type base: int or Decimal
:param rounding: Decimal rounding type
:rtype: Decimal
"""
return base * (decimal_number / base).quantize(1, rounding=rounding)
Examples:
>>> from decimal import Decimal, ROUND_UP
>>> round_decimal(Decimal('123.34'), base=5)
Decimal('120')
>>> round_decimal(Decimal('123.34'), base=6, rounding=ROUND_UP)
Decimal('126')
>>> round_decimal(Decimal('123.34'), base=Decimal('0.05'))
Decimal('123.30')
>>> round_decimal(Decimal('123.34'), base=Decimal('0.5'), rounding=ROUND_UP)
Decimal('123.5')
First note this problem (unexpected rounding down) only sometimes occurs when the digit immediately inferior (to the left of) the digit you're rounding to has a 5.
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
But there's an easy solution, I've found that seems to always work, and which doesn't rely upon the import of additional libraries. The solution is to add a 1e-X where X is the length of the number string you're trying to use round on plus 1.
>>> round(0.075,2)
0.07
>>> round(0.075+10**(-2*6),2)
0.08
Aha! So based on this we can make a handy wrapper function, which is standalone and does not need additional import calls...
def roundTraditional(val,digits):
return round(val+10**(-len(str(val))-1))
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 here.

How to identify the tenths part of a float in Python?

After looking at the various math, float, and decimal functions in Python, I haven't found what I'm looking for. In my program, there may be instances when it will return a float and I need the float information so that I can do another function. Let's say based on the user's input the quotient we're working with is 1.4, which I will represent as X.Y. How do I isolate Y so that I can use a FOR statement. (I need the program to do something 4 times in this case.) I've tried playing with the % function, but that returns the remainder, not the value I'm looking for. I've tried math.fmod and math.modf. Again not what I'm looking for. I looked at this example too.
Looks like int((x*10) % 10) will do it:
>>> x = 1.4
>>> int((x*10) % 10)
4
How about
x = 1.4
y = 10 * (x - int(x))
>>> 4
or you could do it as string manipulation
x=1.4
whole,fractional = map(int,str(x).split("."))
afterwards whole is equal to 1 and fractional is equal to 4... and it should work equally well with negative numbers
Using the following method you can get any position in a float. That is, tenths, hundredths, thousandths and so on:
import math
def get_pos_float(num, unit):
if unit >= 10:
num = abs(math.modf(num)[0]) # Get just the fractional part
num *= 10 # Move the decimal point one place to the right
return get_pos_float(num, unit/10)
return int(math.modf(num)[1]) #Return the whole number part
decimalNumber = 13.24
print(get_pos_float(decimalNumber, 10)) # prints the tenths decimal position 2
print(get_pos_float(decimalNumber, 100)) # prints the hundredths decimal position 4
print(get_pos_float(decimalNumber, 1000)) # prints the thousandths decimal position 0

Division by Zero Errors

I have a problem with this question from my professor. Here is the question:
Write the definition of a function typing_speed , that receives two parameters. The first is the number of words that a person has typed (an int greater than or equal to zero) in a particular time interval. The second is the length of the time interval in seconds (an int greater than zero). The function returns the typing speed of that person in words per minute (a float ).
Here is my code:
def typing_speed(num_words,time_interval):
if(num_words >= 0 and time_interval > 0):
factor = float(60 / time_interval)
print factor
return float(num_words/(factor))
I know that the "factor" is getting assigned 0 because its not being rounded properly or something. I dont know how to handle these decimals properly. Float isnt doing anything apparently.
Any help is appreciated, thankyou.
When you call float on the division result, it's after the fact the division was treated as an integer division (note: this is Python 2, I assume). It doesn't help, what does help is initially specify the division as a floating-point division, for example by saying 60.0 (the float version of 60):
factor = 60.0 / time_interval
Another way would be divide 60 by float(time_interval)
Note this sample interaction:
In [7]: x = 31
In [8]: 60 / x
Out[8]: 1
In [9]: 60.0 / x
Out[9]: 1.935483870967742
Sharth meant to say: from __future__ import python
Example:
>>> from __future__ import division
>>> 4/3
1.3333333333333333
>>>

Categories

Resources