Round number to nearest integer
Will round it and change it to integer
You are not assigning
int(round(h)) to any variable. When you call
int(round(h)), it returns the integer number but does nothing else; you have to change that line for:
h = int(round(h))
To assign the new value to
As @plowman said in the comments, Python's
round() doesn't work as one would normally expect, and that's because the way the number is stored as a variable is usually not the way you see it on screen. There are lots of answers that explain this behavior.
One way to avoid this problem is to use the Decimal as stated by this answer.
In order for this answer to work properly without using extra libraries it would be convenient to use a custom rounding function. I came up with the following solution, that as far as I tested avoided all the storing issues. It is based on using the string representation, obtained with
str()!). It looks hacky but it was the only way I found to solve all the cases. It works with both Python2 and Python3.
def proper_round(num, dec=0): num = str(num)[:str(num).index('.')+dec+2] if num[-1]>='5': return float(num[:-2-(not dec)]+str(int(num[-2-(not dec)])+1)) return float(num[:-1])
Finally, the corrected answer would be:
# Having proper_round defined as previously statedh = int(proper_round(h))
6.39764125, 2)6.31 # should be 6.4proper_round(6.9764125, 1)6.1 # should be 7proper_round(
The gotcha here is that the
dec-th decimal can be 9 and if the
dec+1-th digit >=5 the 9 will become a 0 and a 1 should be carried to the
If we take this into consideration, we get:
def proper_round(num, dec=0): num = str(num)[:str(num).index('.')+dec+2] if num[-1]>='5': a = num[:-2-(not dec)] # integer part b = int(num[-2-(not dec)])+1 # decimal part return float(a)+b**(-dec+1) if a and b == 10 else float(a+str(b)) return float(num[:-1])
In the situation described above
b = 10 and the previous version would just concatenate
b which would result in a concatenation of
10 where the trailing 0 would disappear. This version transforms
b to the right decimal place based on
dec, as a proper carry.
round(x, y). It will round up your number up to your desired decimal place.
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!
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
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