[python] Formatting floats without trailing zeros

How can I format a float so that it doesn't contain trailing zeros? In other words, I want the resulting string to be as short as possible.

For example:

3 -> "3"
3. -> "3"
3.0 -> "3"
3.1 -> "3.1"
3.14 -> "3.14"
3.140 -> "3.14"

This question is related to python formatting floating-point pretty-print

The answer is


You can use max() like this:

print(max(int(x), x))


You can achieve that in most pythonic way like that:

python3:

"{:0.0f}".format(num)

OP would like to remove superflouous zeros and make the resulting string as short as possible.

I find the %g exponential formatting shortens the resulting string for very large and very small values. The problem comes for values that don't need exponential notation, like 128.0, which is neither very large or very small.

Here is one way to format numbers as short strings that uses %g exponential notation only when Decimal.normalize creates strings that are too long. This might not be the fastest solution (since it does use Decimal.normalize)

def floatToString (inputValue, precision = 3):
    rc = str(Decimal(inputValue).normalize())
    if 'E' in rc or len(rc) > 5:
        rc = '{0:.{1}g}'.format(inputValue, precision)        
    return rc

inputs = [128.0, 32768.0, 65536, 65536 * 2, 31.5, 1.000, 10.0]

outputs = [floatToString(i) for i in inputs]

print(outputs)

# ['128', '32768', '65536', '1.31e+05', '31.5', '1', '10']

You could use %g to achieve this:

'%g'%(3.140)

or, with Python = 2.6:

'{0:g}'.format(3.140)

From the docs for format: g causes (among other things)

insignificant trailing zeros [to be] removed from the significand, and the decimal point is also removed if there are no remaining digits following it.


Here's the answer:

import numpy

num1 = 3.1400
num2 = 3.000
numpy.format_float_positional(num1, 3, trim='-')
numpy.format_float_positional(num2, 3, trim='-')

output "3.14" and "3"

trim='-' removes both the trailing zero's, and the decimal.


Handling %f and you should put

%.2f

, where: .2f == .00 floats.

Example:

print "Price: %.2f" % prices[product]

output:

Price: 1.50


Using the QuantiPhy package is an option. Normally QuantiPhy is used when working with numbers with units and SI scale factors, but it has a variety of nice number formatting options.

    >>> from quantiphy import Quantity

    >>> cases = '3 3. 3.0 3.1 3.14 3.140 3.14000'.split()
    >>> for case in cases:
    ...    q = Quantity(case)
    ...    print(f'{case:>7} -> {q:p}')
          3 -> 3
         3. -> 3
        3.0 -> 3
        3.1 -> 3.1
       3.14 -> 3.14
      3.140 -> 3.14
    3.14000 -> 3.14

And it will not use e-notation in this situation:

    >>> cases = '3.14e-9 3.14 3.14e9'.split()
    >>> for case in cases:
    ...    q = Quantity(case)
    ...    print(f'{case:>7} -> {q:,p}')
    3.14e-9 -> 0
       3.14 -> 3.14
     3.14e9 -> 3,140,000,000

An alternative you might prefer is to use SI scale factors, perhaps with units.

    >>> cases = '3e-9 3.14e-9 3 3.14 3e9 3.14e9'.split()
    >>> for case in cases:
    ...    q = Quantity(case, 'm')
    ...    print(f'{case:>7} -> {q}')
       3e-9 -> 3 nm
    3.14e-9 -> 3.14 nm
          3 -> 3 m
       3.14 -> 3.14 m
        3e9 -> 3 Gm
     3.14e9 -> 3.14 Gm

"{:.5g}".format(x)

I use this to format floats to trail zeros.


You can simply use format() to achieve this:

format(3.140, '.10g') where 10 is the precision you want.


Here's a solution that worked for me. It's a blend of the solution by PolyMesh and use of the new .format() syntax.

for num in 3, 3., 3.0, 3.1, 3.14, 3.140:
    print('{0:.2f}'.format(num).rstrip('0').rstrip('.'))

Output:

3
3
3
3.1
3.14
3.14

After looking over answers to several similar questions, this seems to be the best solution for me:

def floatToString(inputValue):
    return ('%.15f' % inputValue).rstrip('0').rstrip('.')

My reasoning:

%g doesn't get rid of scientific notation.

>>> '%g' % 0.000035
'3.5e-05'

15 decimal places seems to avoid strange behavior and has plenty of precision for my needs.

>>> ('%.15f' % 1.35).rstrip('0').rstrip('.')
'1.35'
>>> ('%.16f' % 1.35).rstrip('0').rstrip('.')
'1.3500000000000001'

I could have used format(inputValue, '.15f'). instead of '%.15f' % inputValue, but that is a bit slower (~30%).

I could have used Decimal(inputValue).normalize(), but this has a few issues as well. For one, it is A LOT slower (~11x). I also found that although it has pretty great precision, it still suffers from precision loss when using normalize().

>>> Decimal('0.21000000000000000000000000006').normalize()
Decimal('0.2100000000000000000000000001')
>>> Decimal('0.21000000000000000000000000006')
Decimal('0.21000000000000000000000000006')

Most importantly, I would still be converting to Decimal from a float which can make you end up with something other than the number you put in there. I think Decimal works best when the arithmetic stays in Decimal and the Decimal is initialized with a string.

>>> Decimal(1.35)
Decimal('1.350000000000000088817841970012523233890533447265625')
>>> Decimal('1.35')
Decimal('1.35')

I'm sure the precision issue of Decimal.normalize() can be adjusted to what is needed using context settings, but considering the already slow speed and not needing ridiculous precision and the fact that I'd still be converting from a float and losing precision anyway, I didn't think it was worth pursuing.

I'm not concerned with the possible "-0" result since -0.0 is a valid floating point number and it would probably be a rare occurrence anyway, but since you did mention you want to keep the string result as short as possible, you could always use an extra conditional at very little extra speed cost.

def floatToString(inputValue):
    result = ('%.15f' % inputValue).rstrip('0').rstrip('.')
    return '0' if result == '-0' else result

For float you could use this:

def format_float(num):
    return ('%i' if num == int(num) else '%s') % num

Test it:

>>> format_float(1.00000)
'1'
>>> format_float(1.1234567890000000000)
'1.123456789'

For Decimal see solution here: https://stackoverflow.com/a/42668598/5917543


While formatting is likely that most Pythonic way, here is an alternate solution using the more_itertools.rstrip tool.

import more_itertools as mit


def fmt(num, pred=None):
    iterable = str(num)
    predicate = pred if pred is not None else lambda x: x in {".", "0"}
    return "".join(mit.rstrip(iterable, predicate))

assert fmt(3) == "3"
assert fmt(3.) == "3"
assert fmt(3.0) == "3"
assert fmt(3.1) == "3.1"
assert fmt(3.14) == "3.14"
assert fmt(3.140) == "3.14"
assert fmt(3.14000) == "3.14"
assert fmt("3,0", pred=lambda x: x in set(",0")) == "3"

The number is converted to a string, which is stripped of trailing characters that satisfy a predicate. The function definition fmt is not required, but it is used here to test assertions, which all pass. Note: it works on string inputs and accepts optional predicates.

See also details on this third-party library, more_itertools.


What about trying the easiest and probably most effective approach? The method normalize() removes all the rightmost trailing zeros.

from decimal import Decimal

print (Decimal('0.001000').normalize())
# Result: 0.001

Works in Python 2 and Python 3.

-- Updated --

The only problem as @BobStein-VisiBone pointed out, is that numbers like 10, 100, 1000... will be displayed in exponential representation. This can be easily fixed using the following function instead:

from decimal import Decimal


def format_float(f):
    d = Decimal(str(f));
    return d.quantize(Decimal(1)) if d == d.to_integral() else d.normalize()

If you can live with 3. and 3.0 appearing as "3.0", a very simple approach that right-strips zeros from float representations:

print("%s"%3.140)

(thanks @ellimilial for pointing out the exceptions)


>>> str(a if a % 1 else int(a))

Use %g with big enough width, for example '%.99g'. It will print in fixed-point notation for any reasonably big number.

EDIT: it doesn't work

>>> '%.99g' % 0.0000001
'9.99999999999999954748111825886258685613938723690807819366455078125e-08'

Examples related to python

programming a servo thru a barometer Is there a way to view two blocks of code from the same file simultaneously in Sublime Text? python variable NameError Why my regexp for hyphenated words doesn't work? Comparing a variable with a string python not working when redirecting from bash script is it possible to add colors to python output? Get Public URL for File - Google Cloud Storage - App Engine (Python) Real time face detection OpenCV, Python xlrd.biffh.XLRDError: Excel xlsx file; not supported Could not load dynamic library 'cudart64_101.dll' on tensorflow CPU-only installation

Examples related to formatting

How to add empty spaces into MD markdown readme on GitHub? VBA: Convert Text to Number How to change indentation in Visual Studio Code? How do you change the formatting options in Visual Studio Code? (Excel) Conditional Formatting based on Adjacent Cell Value 80-characters / right margin line in Sublime Text 3 Format certain floating dataframe columns into percentage in pandas Format JavaScript date as yyyy-mm-dd AngularJS format JSON string output converting multiple columns from character to numeric format in r

Examples related to floating-point

Convert list or numpy array of single element to float in python Convert float to string with precision & number of decimal digits specified? Float and double datatype in Java C convert floating point to int Convert String to Float in Swift How do I change data-type of pandas data frame to string with a defined format? How to check if a float value is a whole number Convert floats to ints in Pandas? Converting Float to Dollars and Cents Format / Suppress Scientific Notation from Python Pandas Aggregation Results

Examples related to pretty-print

Print a list of space-separated elements in Python 3 Printing out a linked list using toString How can I pretty-print JSON using Go? JSON.stringify output to div in pretty print way Convert JSON String to Pretty Print JSON output using Jackson How to prettyprint a JSON file? Pretty-print a Map in Java Pretty-Print JSON Data to a File using Python How do I pretty-print existing JSON data with Java? Pretty-Printing JSON with PHP