round down to 2 decimal in python
It seems you want truncation, not rounding.
A simple way would be to combine floor division //
and regular division /
:
>>> a = 28.266
>>> a // 0.01 / 100
28.26
Instead of the regular division you could also multiply (as noted in the comments by cmc):
>>> a // 0.01 * 0.01
28.26
Similarly you could create a function to round down to other more/less decimals. But because floats are inexact numbers, this can lead to inaccuracies.
def round_down(value, decimals):
factor = 1 / (10 ** decimals)
return (value // factor) * factor
print(round_down(28.266, 2))
# 28.26
But as said it's not exactly exact:
for i in range(0, 8):
print(i, round_down(12.33333, i))
0 12.0
1 12.3
2 12.33
3 12.333
4 12.333300000000001 # weird, but almost correct
5 12.33332 # wrong
6 12.33333
7 12.33333
There are other (more precise) approaches though:
A solution using the fraction
module
A fraction
can represent a decimal number much more exact than a float
. Then one can use the "multiply, then floor, then divide" approach mentioned by Psidom but with significantly higher precision:
import fractions
import math
a = 28.266
def round_down(value, decimals):
factor = 10 ** decimals
f = fractions.Fraction(value)
return fractions.Fraction(math.floor(f * factor), factor)
print(round_down(28.266, 2))
# 1413/50 <- that's 28.26
And using the test I did with the floats:
for i in range(0, 8):
print(i, round_down(12.33333, i))
0 12
1 123/10
2 1233/100
3 12333/1000
4 123333/10000
5 1233333/100000
6 1233333/100000
7 1233333/100000
However creating a Fraction
will not magically fix an inexact float
, so typically one should create the Fraction
from a string or a "numerator-denominator pair" instead of from float.
A solution using the decimal
module
You could also use the decimal
module, which offers a variety of rounding modes, including rounding down.
For this demonstration I'm using a context manager to avoid changing the decimal rounding mode globally:
import decimal
def round_down(value, decimals):
with decimal.localcontext() as ctx:
d = decimal.Decimal(value)
ctx.rounding = decimal.ROUND_DOWN
return round(d, decimals)
print(round_down(28.266, 2)) # 28.26
Which gives more sensible results for the rounding:
for i in range(0, 8):
print(i, round_down(12.33333, i))
0 12
1 12.3
2 12.33
3 12.333
4 12.3333
5 12.33333
6 12.333330
7 12.3333300
As with Fraction
a Decimal
should be created from a string to avoid the intermediate inexact float. But different from Fraction
the Decimal
have limited precision, so for values with lots of significant figures it will also become inexact.
However "rounding down" is just one of the available options. The list of available rounding modes is extensive:
Rounding modes
decimal.ROUND_CEILING
Round towards Infinity.
decimal.ROUND_DOWN
Round towards zero.
decimal.ROUND_FLOOR
Round towards -Infinity.
decimal.ROUND_HALF_DOWN
Round to nearest with ties going towards zero.
decimal.ROUND_HALF_EVEN
Round to nearest with ties going to nearest even integer.
decimal.ROUND_HALF_UP
Round to nearest with ties going away from zero.
decimal.ROUND_UP
Round away from zero.
decimal.ROUND_05UP
Round away from zero if last digit after rounding towards zero would have been 0 or 5; otherwise round towards zero.
Seems like you need the floor
:
import math
math.floor(a * 100)/100.0
# 28.26
With Python 3 you can use quantize()
from decimal import *
>>> Decimal('7.325').quantize(Decimal('.01'), rounding=ROUND_DOWN)
Decimal('7.32')