Truncation to N Decimal Places in Python

I recently needed to truncate some IEEE 754 64bit floating point numbers to a given number of decimal places. I assumed Python would have built-in support for this. Not so.

Now there are reasons for this. The primary one being that you can’t really truncate floating point numbers. Now that being said – if you need to – I present here a good way to approximate the effect.

import numpy
import math
def truncFloat( floatValue, decimalPlaces ):
    return math.trunc( numpy.nextafter( floatValue, floatValue + floatValue ) * 
               ( 10.0 ** decimalPlaces ) ) / ( 10 ** decimalPlaces )

So what just happened there ?

The basic bit is the multiply by 10, 100 etc to shift left the number of decimal places we need. math.trunc gives us the truncation to 0dp and then dividing restores the fractional part.

numpy.nextafter is a little bit of hacky magic, since floating point representations are imprecise, adding the minimum possible increment to the number ensures that the result of rounding tends to be more correct by virtue of pushing approximate values like 3.999999999999999 to 4.00000000000001, which clearly will truncate better.

Now there are two further issues, as numbers get very very large (i.e. close to 2**52) truncation becomes meaningless for 64 bit floats, so it may be worth just returning the input. Secondly numpy.nextafter may result it very large values increasing by > 1. My solution to this is to pick a point at which to just start returning floatValue. You could be more sophisticated and pick a cutoff based on the number of decimalPlaces required.

Additionally we can optimize a bit. We may as well use a precomputed array for decimalPlaces ** 10. I don’t get too obsessed with optimization in Python since it’s pretty slow to start with. If you need fast, rewrite in C++.

One thing to watch is the portability of numpy.nextafter – you may have to be careful on some more niche platforms.

Enjoy.