20

I am trying to truncate a decimal value in Python. I don't want to round it, but instead just display the decimal values upto the specified accuracy. I tried the following:

d = 0.989434
'{:.{prec}f}'.format(d, prec=2)

This rounds it to 0.99. But I actually want the output to be 0.98. Obviously, round() is not an option. Is there any way to do this? Or should I go back to the code and change everything to decimal?

Thanks.

Taylan Aydinli
  • 4,333
  • 15
  • 39
  • 33
visakh
  • 2,503
  • 8
  • 29
  • 55

12 Answers12

17

You can use following code

import decimal
d = 0.989434

print decimal.Decimal(d).quantize(decimal.Decimal('.01'), rounding=decimal.ROUND_DOWN)
Nilani Algiriyage
  • 32,876
  • 32
  • 87
  • 121
9

I am not aware of all your requirements, but this will be fairly robust.

>> before_dec, after_dec = str(d).split('.')
>> float('.'.join((before_dec, after_dec[0:2])))
0.98

2018-01-03 edit

This answer isn't robust or mathematically correct. See Nilani Algiriyage's answer below for the correct way to do this using Decimal.quantize method.

Jesse Dhillon
  • 7,841
  • 1
  • 34
  • 34
Derek Litz
  • 10,529
  • 7
  • 43
  • 53
  • 1
    `after_dec[:2]` is enough :) – thefourtheye Dec 12 '13 at 13:31
  • It sure is, but I believe that convention makes more sense in the case where the the other side is unknown, i.e. `a_list[3:]` so I don't really pay much attention to `[0:2]` vs `[:2]`, whichever comes out at the time is good enough :) – Derek Litz Dec 12 '13 at 13:42
  • 1
    Why did you accept this as the solution? :) I would find some of the math based solutions slightly more robust! – James Mills Dec 12 '13 at 13:44
  • @James Mills The only not robust part is if there is no decimal place, and surely you can figure out how to deal with that :) – Derek Litz Dec 12 '13 at 13:46
  • 1
    Just curious is all :) I would use the ``Decimal`` or any of the other math-based solutions personally! *I totally forgot that floating-point string formatting specifiers do rounding!* :/ – James Mills Dec 12 '13 at 13:48
  • Yeah, I am curious of the OP's opinion too, but if I were to guess, the math makes it harder to understand and is not necessary for this case. – Derek Litz Dec 12 '13 at 13:49
  • 1
    if i were to guess: he probably just wanted to do this on only one number, and as soon as he got a working solution he accepted it, without bothering to read the others... – Kraay89 Dec 12 '13 at 13:54
  • @JamesMills to be frank, my browser didn't update with your solution when I accepted Derek's solution..also, Derek's solution was pretty straightforward and is more than enough in the particular instance I am working on... – visakh Dec 12 '13 at 13:56
  • @Kraay89 not exactly...blame it on IE for not loading the page...:-) – visakh Dec 12 '13 at 13:56
  • My solution was incorrect anyway, so that doesn't matter. All good! – James Mills Dec 12 '13 at 13:57
  • Thanks to all of you...:-) – visakh Dec 12 '13 at 13:58
  • @user295338 i'm sorry. Your generic name made me jump to conclusions (i'll go wash my mouth now) – Kraay89 Dec 12 '13 at 13:58
  • @Kraay89 No probs...I was also bit hasty in closing this question (wanted to get home early :-)) – visakh Dec 12 '13 at 14:01
  • Unfortunately, this answer comes up as the top answer in Google for this question. `decimal` has a built-in, mathematically-correct way to do this, and Nilani Algiriyage's answer shows how. – Jesse Dhillon Jan 04 '18 at 01:25
6
d = 0.989434
print floor(d * 100) / 100

Math.floor(x) Return the floor of x as a float, the largest integer value less than or equal to x.

Moving the 2 decimals on the left of the decimal '.', flooring, then moving back the numbers on the right of the '.'

100 can be modifying by

n = 2
m = pow (10, n)
d = 0.989434
print floor(d * m) / m

n is your wanted precision.

EDIT: In case d is negative, you have to use the ceil method

if d < 0:
    print ceil(d * m) / m
else:
    print floor(d * m) / m
Marcassin
  • 1,386
  • 1
  • 11
  • 21
3

Format it to something much longer and then cut off the extra digits:

def truncate(f, digits):
    return ("{:.30f}".format(f))[:-30+digits]
RemcoGerlich
  • 30,470
  • 6
  • 61
  • 79
3
import math

d = 0.989434
prec = 2
output = math.floor(d * (10 ** prec)) / (10 ** prec)

If you still want a decimal variable instead of string

Ray
  • 2,472
  • 18
  • 22
  • Note that for `d = -0.989434` this prints `-0.99` – Eric Dec 18 '13 at 19:27
  • @Eric Yeah you are right! That comes from the definition of `floor`. Seems that better to use string formatting. :) – Ray Dec 19 '13 at 02:43
3

This is the best way I believe.

  1. Move the significant digits to the left
  2. Truncate the decimal part
  3. Move the number of digits moved to left, to right

    d = 0.989434
    print "{0:0.2f}".format(int(d * 100)/100.0)
    

    Output

    0.98
    
thefourtheye
  • 233,700
  • 52
  • 457
  • 497
1

Also with math:

d = 0.989434
x = int(d * 100.0) / 100.0
print "{0:0.2f}".format(x)
James Mills
  • 18,669
  • 3
  • 49
  • 62
1

The code below will print 0.98 in this case, though you'll have to be careful that your d value doesn't become larger than or equal to 10 as then it'll only print, for e.g., 10.1 rather than 10.12.

d = 0.989434
print '{:.{prec}s}'.format(str(d), prec=4)
Ffisegydd
  • 51,807
  • 15
  • 147
  • 125
1

with str:

d = str(0.989434)
print float(d[:d.find('.')+3])
onionpsy
  • 1,502
  • 11
  • 15
1

If you only need to display you can convert it to string and slice it :

d = 0.989434
print str(d)[0:4] #or print(str(d)[0:4])
feydaykyn
  • 666
  • 7
  • 7
1

Fairly similar to some other answers, but without any imports

def truncate(x, d):
    return int(x*(10.0**d))/(10.0**d)

>>>truncate(0.987654, 2)
0.98
Kraay89
  • 919
  • 1
  • 7
  • 19
0

In this link here I posted the solution below:

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

At leat it doesn't require to load any module nor demands new calculations. So far, it solved my problem with the truncation requirements in public bond prices calculations.

Eduardo Alvim
  • 201
  • 2
  • 4