# Truncate to three decimals in Python

## Question:

How do I get 1324343032.324?

As you can see below, the following do not work:

``````>>1324343032.324325235 * 1000 / 1000
1324343032.3243253
>>int(1324343032.324325235 * 1000) / 1000.0
1324343032.3239999
>>round(int(1324343032.324325235 * 1000) / 1000.0,3)
1324343032.3239999
>>str(1324343032.3239999)
'1324343032.32'
``````

You can use an additional `float()` around it if you want to preserve it as a `float`.

``````val = '%.3f'%(1324343032.324325235)
``````

``````In : '%.3f' % round(1324343032.324325235 * 1000 / 1000,3)
Out: '1324343032.324'
``````

Possible duplicate of round() in Python doesn't seem to be rounding properly

[EDIT]

``````In : Decimal('%.3f' % (1324343032.324325235 * 1000 / 1000))
Out: Decimal('1324343032.324')
``````

The floating point accuracy isn’t going to be what you want:

``````In : 3.324
Out: 3.3239999999999998
``````

(all examples are with Python 2.6.5)

Almo’s link explains why this happens. To solve the problem, use the decimal library.

Use the decimal module. But if you must use floats and still somehow coerce them into a given number of decimal points converting to string an back provides a (rather clumsy, I’m afraid) method of doing it.

``````>>> q = 1324343032.324325235 * 1000 / 1000
>>> a = "%.3f" % q
>>> a
'1324343032.324'
>>> b = float(a)
>>> b
1324343032.324
``````

So:

``````float("%3.f" % q)
``````

You can use the following function to truncate a number to a set number of decimals:

``````import math
def truncate(number, digits) -> float:
# Improve accuracy with floating point operations, to avoid truncate(16.4, 2) = 16.39 or truncate(-1.13, 2) = -1.12
nbDecimals = len(str(number).split('.'))
if nbDecimals <= digits:
return number
stepper = 10.0 ** digits
return math.trunc(stepper * number) / stepper
``````

Usage:

``````>>> truncate(1324343032.324325235, 3)
1324343032.324
``````

I’ve found another solution (it must be more efficient than “string witchcraft” workarounds):

``````>>> import decimal
# By default rounding setting in python is decimal.ROUND_HALF_EVEN
>>> decimal.getcontext().rounding = decimal.ROUND_DOWN
>>> c = decimal.Decimal(34.1499123)
# By default it should return 34.15 due to '99' after '34.14'
>>> round(c,2)
Decimal('34.14')
>>> float(round(c,2))
34.14
>>> print(round(c,2))
34.14
``````

``````>>> float(1324343032.324325235) * float(1000) / float(1000)

1324343032.3243253

>>> round(float(1324343032.324325235) * float(1000) / float(1000), 3)

1324343032.324
``````

You can also use:

``````import math

nValeur = format(float(input('Quelle valeur ?    ')), '.3f')
``````

In Python 3.6 it would work.

After looking for a way to solve this problem, without loading any Python 3 module or extra mathematical operations, I solved the problem using only str.format() e .float(). I think this way is faster than using other mathematical operations, like in the most commom solution. I needed a fast solution because I work with a very very large dataset and so for its working very well here.

``````def truncate_number(f_number, n_decimals):
strFormNum = "{0:." + str(n_decimals+5) + "f}"
trunc_num = float(strFormNum.format(f_number)[:-5])
return(trunc_num)

# Testing the 'trunc_num()' function
test_num = 1150/252
[(idx, truncate_number(test_num, idx)) for idx in range(0, 20)]
``````

It returns the following output:

``````[(0, 4.0),
(1, 4.5),
(2, 4.56),
(3, 4.563),
(4, 4.5634),
(5, 4.56349),
(6, 4.563492),
(7, 4.563492),
(8, 4.56349206),
(9, 4.563492063),
(10, 4.5634920634),
(11, 4.56349206349),
(12, 4.563492063492),
(13, 4.563492063492),
(14, 4.56349206349206),
(15, 4.563492063492063),
(16, 4.563492063492063),
(17, 4.563492063492063),
(18, 4.563492063492063),
(19, 4.563492063492063)]
``````

I believe using the `format` function is a bad idea. Please see the below. It rounds the value. I use Python 3.6.

``````>>> '%.3f'%(1.9999999)
'2.000'
``````

``````>>> re.match(r'd+.d{3}', str(1.999999)).group(0)
'1.999'
``````

‘%.3f’%(1324343032.324325235)

It’s OK just in this particular case.

Simply change the number a little bit:

1324343032.324725235

And then:

``````'%.3f'%(1324343032.324725235)
``````

gives you 1324343032.325

``````def trun_n_d(n,d):
s=repr(n).split('.')
if (len(s)==1):
return int(s)
return float(s+'.'+s[:d])
``````

Another option for trun_n_d:

``````def trun_n_d(n,d):
dp = repr(n).find('.') #dot position
if dp == -1:
return int(n)
return float(repr(n)[:dp+d+1])
``````

Yet another option ( a oneliner one) for trun_n_d [this, assumes ‘n‘ is a str and ‘d‘ is an int]:

``````def trun_n_d(n,d):
return (  n if not n.find('.')+1 else n[:n.find('.')+d+1]  )
``````

trun_n_d gives you the desired output in both, Python 2.7 and Python 3.6

trun_n_d(1324343032.324325235,3) returns 1324343032.324

Likewise, trun_n_d(1324343032.324725235,3) returns 1324343032.324

Note 1 In Python 3.6 (and, probably, in Python 3.x) something like this, works just fine:

``````def trun_n_d(n,d):
return int(n*10**d)/10**d
``````

But, this way, the rounding ghost is always lurking around.

Note 2 In situations like this, due to python‘s number internals, like rounding and lack of precision, working with n as a str is way much better than using its int counterpart; you can always cast your number to a float at the end.

Maybe this way:

``````def myTrunc(theNumber, theDigits):

myDigits = 10 ** theDigits
return (int(theNumber * myDigits) / myDigits)
``````

Okay, this is just another approach to solve this working on the number as a string and performing a simple slice of it. This gives you a truncated output of the number instead of a rounded one.

``````num = str(1324343032.324325235)
i = num.index(".")
truncated = num[:i + 4]

print(truncated)
``````

Output:

``````'1324343032.324'
``````

Of course then you can parse:

``````float(truncated)
``````
``````a = 1.0123456789
dec = 3 # keep this many decimals
p = 10 # raise 10 to this power
a * 10 ** p // 10 ** (p - dec) / 10 ** dec
>>> 1.012
``````

I think the best and proper way is to use `decimal` module.

``````import decimal

a = 1324343032.324325235

decimal_val = decimal.Decimal(str(a)).quantize(
decimal.Decimal('.001'),
rounding=decimal.ROUND_DOWN
)
float_val = float(decimal_val)

print(decimal_val)
>>>1324343032.324

print(float_val)
>>>1324343032.324
``````

You can use different values for `rounding=decimal.ROUND_DOWN`, available options are `ROUND_CEILING`, `ROUND_DOWN`, `ROUND_FLOOR`, `ROUND_HALF_DOWN`, `ROUND_HALF_EVEN`, `ROUND_HALF_UP`, `ROUND_UP`, and `ROUND_05UP`. You can find explanation of each option here in docs.

Maybe python changed since this question, all of the below seem to work well

Python2.7

``````int(1324343032.324325235 * 1000) / 1000.0
float(int(1324343032.324325235 * 1000)) / 1000
round(int(1324343032.324325235 * 1000) / 1000.0,3)
# result for all of the above is 1324343032.324
``````

I suggest next solution:

``````def my_floor(num, precision):
return f'{num:.{precision+1}f}'[:-1]

my_floor(1.026456,2) # 1.02

``````

I am trying to generate a random number between 5 to 7 and want to limit it to 3 decimal places.

``````import random

num = float('%.3f' % random.uniform(5, 7))
print (num)
``````

## Function

``````def truncate(number: float, digits: int) -> float:
pow10 = 10 ** digits
return number * pow10 // 1 / pow10
``````

## Test code

``````f1 = 1.2666666
f2 = truncate(f1, 3)
print(f1, f2)
``````

## Output

``````1.2666666 1.266
``````

## Explain

It shifts `f1` numbers `digits` times to the left, then cuts all decimals and finally shifts back the numbers `digits` times to the right.

Example in a sequence:

``````1.2666666 # number
1266.6666 # number * pow10
1266.0    # number * pow10 // 1
1.266     # number * pow10 // 1 / pow10
``````

I develop a good solution, I know there is much `If` statements, but It works! (Its only for <1 numbers)

``````def truncate(number, digits) -> float:
startCounting = False
if number < 1:
number_str = str('{:.20f}'.format(number))
resp = ''
count_digits = 0
for i in range(0, len(number_str)):
if number_str[i] != '0' and number_str[i] != '.' and number_str[i] != ',':
startCounting = True
if startCounting:
count_digits = count_digits + 1
resp = resp + number_str[i]
if count_digits == digits:
break
return resp
else:
return number
``````

Based on @solveMe asnwer (https://stackoverflow.com/a/39165933/641263) which I think is one of the most correct ways by utilising decimal context, I created following method which does the job exactly as needed:

``````import decimal

def truncate_decimal(dec: Decimal, digits: int) -> decimal.Decimal:
round_down_ctx = decimal.getcontext()
round_down_ctx.rounding = decimal.ROUND_DOWN
new_dec = round_down_ctx.create_decimal(dec)
return round(new_dec, digits)
``````

Another way in comparison with the accepted answer is to use a more modern formatted string literal (f-string):

``````>>> f'{1324343032.324325235:.3f}'
>>> '1324343032.324'
``````
Categories: questions Tags:
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.