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 

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 

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

I suggest next solution:

def my_floor(num, precision): return f'{num:.{precision+1}f}'[:-1] my_floor(1.026456,2) # 1.02 
1

You can also use:

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

In Python 3.6 it would work.

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 

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

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 () 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) 
>>> float(1324343032.324325235) * float(1000) / float(1000) 1324343032.3243253 >>> round(float(1324343032.324325235) * float(1000) / float(1000), 3) 1324343032.324 
1

Your Answer

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

You Might Also Like