Truncate to Three Decimals in Python

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'
6

21 Answers

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

%.3f'%(1324343032.324325235)
12

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('.')[1]) 
    if nbDecimals <= digits:
        return number
    stepper = 10.0 ** digits
    return math.trunc(stepper * number) / stepper

Usage:

>>> truncate(1324343032.324325235, 3)
1324343032.324
5

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

About decimals module

About rounding settings

2

How about this:

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

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

[EDIT]

Given the additional comments I believe you'll want to do:

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)

'%.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

Try this instead:

def trun_n_d(n,d):
    s=repr(n).split('.')
    if (len(s)==1):
        return int(s[0])
    return float(s[0]+'.'+s[1][: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.

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)
1

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'

Use a regular expression instead:

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

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

Maybe this way:

def myTrunc(theNumber, theDigits):

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

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)

Function

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

Sophia Al-Mansoor

Global Business & E-Commerce Reporter

Sophia analyzes international trade, startup ecosystems, retail transformation, and supply chain logistics for modern digital publications.