Home > other >  Fixed number of digits for size regardless of case/unit
Fixed number of digits for size regardless of case/unit

Time:12-30

I have the following code:

def format_sizeof(num, suffix='', divisor=1000):
    """
    Formats a number (greater than unity) with SI Order of Magnitude
    prefixes.
    Parameters
    ----------
    num  : float
        Number ( >= 1) to format.
    suffix  : str, optional
        Post-postfix [default: ''].
    divisor  : float, optional
        Divisor between prefixes [default: 1000].
    Returns
    -------
    out  : str
        Number with Order of Magnitude SI unit postfix.
    """
    for unit in ['', 'k', 'M', 'G', 'T', 'P', 'E', 'Z']:
        if abs(num) < 999.5:
            if abs(num) < 99.95:
                if abs(num) < 9.995:
                    return '{0:1.2f}'.format(num)   unit   suffix
                return '{0:2.1f}'.format(num)   unit   suffix
            return '{0:3.0f}'.format(num)   unit   suffix
        num /= divisor
    return '{0:3.1f}Y'.format(num)   suffix

What I am looking to do is to adapt it so that it always prints the same number of digits, regardless of the case/unit, while still maintaining human readability.

This is to ensure that the same width is printed every time the terminal flushes.

I came across several approaches, padding, string typecasting, math.log10.

I am not sure what is the best way to exactly go about solving this.

Thanks in advance.

CodePudding user response:

From the documentation on string formatting:

width is a decimal integer defining the minimum total field width, including any prefixes, separators, and other formatting characters. If not specified, then the field width will be determined by the content.

The precision is a decimal number indicating how many digits should be displayed after the decimal point for a floating point value formatted with 'f' and 'F', or before and after the decimal point for a floating point value formatted with 'g' or 'G'. For non-number types the field indicates the maximum field size - in other words, how many characters will be used from the field content. The precision is not allowed for integer values.

In other words, for a floating-point with 'g', width gives the minimum number of characters, including digits and decimal point, and precision gives the maximum number of digits.

The width is the number before the dot in the format string. The precision is the number after the dot in the format string.

Here is an example with a precision of 5 (maximum 5 digits), and a width of 6 (minimum 5 digits 1 decimal point):

>>> '{:6.5g}'.format(123.4567)
'123.46'
>>> '{:6.5g}'.format(12.34567)
'12.346'
>>> '{:6.5g}'.format(12.1)
'  12.1'
>>> '{:6.5g}'.format(12.0)
'    12'

CodePudding user response:

If you want to print a number using n digits (and you're sure you don't need more than n):

from math import log10

x = 42
n = 5
print(format(x, f'{n}.{n-1-int(log10(x))}f'))

Result:

42.000

log10 is separate from the other math functions, so fairly optimised, although since you're only interested in the integer part of it, you might be able to get a bit faster still.

  • Related