I have a beginner problem. How can I round up to 2 decimal? Here is what I tried and what I want to achieve:
import math
var_1 = 14.063 # expected = 14.06
var_2 = 10.625 # expected = 10.63
print(round(14.063, 2))
print(round(10.625, 2))
print('===========================')
def round_up(n, decimals=0):
multiplier = 10 ** decimals
return math.ceil(n * multiplier) / multiplier
print(round_up(var_1, 2))
print(round_up(var_2, 2))
And the Output is:
14.06
10.62
===========================
14.07
10.63
So neither of those wroks for me...
CodePudding user response:
The Decimal class, quantize() method, and ROUND_HALF_UP rule from the decimal module can handle this:
from decimal import Decimal, ROUND_HALF_UP
var_1 = 14.063 # expected = 14.06
var_2 = 10.625 # expected = 10.63
# a Decimal object with an explicit exponent attribute/property (to be interpreted by quantize)
dec_w_exp = Decimal("1e-2")
for var in [var_1, var_2]:
rounded = Decimal(var).quantize(dec_w_exp, rounding=ROUND_HALF_UP)
print(f"decimal: {rounded}")
print(f"float: {float(rounded)}")
and I get:
decimal: 14.06
float: 14.06
decimal: 10.63
float: 10.63
Keep in mind that when you're dealing with floats, you're always manipulating a less-than-precise representation of what you probably (naturally) have in mind:
Decimal(1.65) # Decimal('1.649999999999999911182158029987476766109466552734375')
Decimal('1.65') # Decimal('1.65')
In the first case, 1.65 was first turned into an IEEE-754 float, which has rounding errors going from base-10 to base-2, then passed to Decimal. In the second case, Decimal interpreted the number as "one, and 65 100-ths" which equates to "165 times 10 raised to the minus 2", or 165E-2
.
CodePudding user response:
this should work, although there is probebly a more efficient way of doing it. I just tool your code and determined which one was closer, and if they are the same to round up.
import math
decimals = 2
var_1 = 14.063
var_2 = 10.625
var_1down = round(var_1, decimals)
var_2down = round(var_2, decimals)
def round_up(n, decimals=0):
multiplier = 10 ** decimals
return math.ceil(n * multiplier) / multiplier
var_1up = round_up(var_1, decimals)
var_2up = round_up(var_2, decimals)
if var_1 - var_1down >= var_1up - var_1:
var_1round = var_1up
else:
var_1round = var_1down
if var_2 - var_2down >= var_2up - var_2:
var_2round = var_2up
else:
var_2round = var_2down
print (var_1round)
print (var_2round)
CodePudding user response:
Try this. This finds the nearest one and if not, then round up -
import math
v1 = 14.063
v2 = 10.625
def round_up(n, decimals=0):
multiplier = 10 ** decimals
var_down = round(n, 2)
var_up = math.ceil(n * multiplier) / multiplier
if n - var_down >= var_up - n:
return var_up
else:
return var_down
v1_round = round_up(v1, 2)
v2_round = round_up(v2, 2)
print (v1_round) # 14.06
print (v2_round) # 10.63
CodePudding user response:
This is a feature of Python 3
and it behaves as expected. It uses round half to even whereby a number is rounded to nearest value and ties are rounded to nearest even least significant digit (or right most digit). See this tutorial for more information, as well as this StackOverflow post for additional information.
Python 2
, however, behaves as you would like. For example, round(10.625, 2)
is rounded up to 10.63
.
CodePudding user response:
If you check the docs you will see that "values are rounded to the closest multiple of 10 to the power minus ndigits; if two multiples are equally close, rounding is done toward the even choice (so, for example, both round(0.5) and round(-0.5) are 0, and round(1.5) is 2)".
So 10.625 rounds to 10.62. You may try adding a very small value, e.g. 0.00001, but even so, since the way float numbers work, you may have some surprise in a few cases.