Reputation: 22549
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'
Upvotes: 99
Views: 275114
Reputation: 5916
You can use an additional float()
around it if you want to preserve it as a float
.
val = '%.3f'%(1324343032.324325235)
Upvotes: 95
Reputation: 18670
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
Upvotes: 90
Reputation: 2329
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)
Upvotes: 1
Reputation: 9
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
Upvotes: -1
Reputation: 563
def truncate(number: float, digits: int) -> float:
pow10 = 10 ** digits
return number * pow10 // 1 / pow10
f1 = 1.2666666
f2 = truncate(f1, 3)
print(f1, f2)
1.2666666 1.266
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
Upvotes: 6
Reputation: 2272
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)
Upvotes: 2
Reputation: 4892
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)
Upvotes: -1
Reputation: 161
I suggest next solution:
def my_floor(num, precision):
return f'{num:.{precision+1}f}'[:-1]
my_floor(1.026456,2) # 1.02
Upvotes: 5
Reputation: 10523
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
Upvotes: 0
Reputation: 7242
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.
Upvotes: 4
Reputation: 969
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
Upvotes: 0
Reputation: 1709
'%.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.
Upvotes: 7
Reputation: 41
Maybe this way:
def myTrunc(theNumber, theDigits):
myDigits = 10 ** theDigits
return (int(theNumber * myDigits) / myDigits)
Upvotes: 4
Reputation: 111
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'
Upvotes: 6
Reputation: 11
You can also use:
import math
nValeur = format(float(input('Quelle valeur ? ')), '.3f')
In Python 3.6 it would work.
Upvotes: 0
Reputation: 341
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)]
Upvotes: 1
Reputation: 1
>>> float(1324343032.324325235) * float(1000) / float(1000)
1324343032.3243253
>>> round(float(1324343032.324325235) * float(1000) / float(1000), 3)
1324343032.324
Upvotes: -1
Reputation: 2101
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
Upvotes: 36
Reputation: 15167
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)
Upvotes: 14
Reputation: 457
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)
Upvotes: 6
Reputation: 14910
Almo's link explains why this happens. To solve the problem, use the decimal library.
Upvotes: 2