Python: How do I format numbers for a fixed width?
Asked Answered
A

2

9

let's say

numbers = [ 0.7653, 10.2, 100.2325, 500.9874 ]

I'd like to output the numbers with a fixed width by varying the number of decimal places to get an output like this:

0.7653
10.200
100.23
500.98

is there an easy way to do this? I've been trying with various %f and %d configurations with no luck.

Ardolino answered 25/7, 2014 at 16:22 Comment(1)
Shouldn't the last one round to 500.99?Bluegreen
N
20

Combining two str.format / format calls:

numbers = [ 0.7653, 10.2, 100.2325, 500.9874 ]
>>> for n in numbers:
...     print('{:.6s}'.format('{:0.4f}'.format(n)))
...     #  OR format(format(n, '0.4f'), '.6s')
...
0.7653
10.200
100.23
500.98

or % operators:

>>> for n in numbers:
...     print('%.6s' % ('%.4f' % n))
...
0.7653
10.200
100.23
500.98

Alternatively, you can use slicing:

>>> for n in numbers:
...     print(('%.4f' % n)[:6])
...
0.7653
10.200
100.23
500.98
Nanceenancey answered 25/7, 2014 at 16:27 Comment(1)
Note that these solutions don't round the final decimal.Bluegreen
I
5

Unfortunately, there is no out-of-box solution for this problem. Moreover, the solution with string slicing does not adequately handles rounding as well as overflows.

Therefore, it seems that one has to write an own function like this:

def to_fixed_width(n, max_width, allow_overflow = True, do_round = True):
    if do_round:
        for i in range(max_width - 2, -1, -1):
            str0 = '{:.{}f}'.format(n, i)
            if len(str0) <= max_width:
                break
    else:
        str0 = '{:.42f}'.format(n)
        int_part_len = str0.index('.')
        if int_part_len <= max_width - 2:
            str0 = str0[:max_width]
        else:
            str0 = str0[:int_part_len]
    if (not allow_overflow) and (len(str0) > max_width):
        raise OverflowError("Impossible to represent in fixed-width non-scientific format")
    return str0

The resulting behavior:

>>> to_fixed_width(0.7653, 6)
'0.7653'
>>> to_fixed_width(10.2, 6)
'10.200'
>>> to_fixed_width(100.2325, 6)
'100.23'
>>> to_fixed_width(500.9874, 6)
'500.99'
>>> to_fixed_width(500.9874, 6, do_round = False)
'500.98'

More examples:

>>> to_fixed_width(-0.3, 6)
'-0.300'
>>> to_fixed_width(0.000001, 6)
'0.0000'
>>> to_fixed_width(999.99, 6)
'999.99'
>>> to_fixed_width(999.999, 6)
'1000.0'
>>> to_fixed_width(1000.4499, 6)
'1000.4'
>>> to_fixed_width(1000.4499, 6, do_round = False)
'1000.4'
>>> to_fixed_width(12345.6, 6)
'12346'
>>> to_fixed_width(1234567, 6)
'1234567'
>>> to_fixed_width(1234567, 6, allow_overflow = False)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 15, in to_fixed_width
OverflowError: Impossible to represent in fixed-width non-scientific format
>>> to_fixed_width(float('nan'), 6)
'nan'
Ionic answered 13/4, 2017 at 16:24 Comment(1)
This is an amazing general use function, thanks @Roman! I exclusively needed the case (allow_overflow=False, do_round=True), so I use a modified version of your function.Mite

© 2022 - 2024 — McMap. All rights reserved.