2
votes

Update: as up to now (2019-09), masking leading or trailing zeros in decimal numbers formatted to string seems to be unsupported in Python. You will need to use a workaround to get something like '.01' from the number 0.0101 (assuming 3 decimal places desired).

I would even argue that it's a good thing not to support such a format since

  • I'd consider '0.01' be better in terms of readability than '.01'
  • '0.010' carries information (3 digits of precision...) that is lost in '0.01'

If desired anyway, one could use one of the suggestions below. Thank you all for contributing.

Q: I'm looking for a way to output floating point numbers as strings, formatted without leading/trailing zeros. Is there a way to do this with '{ }'.format() or f-string? I searched the internet but didn't find anything. Did I just miss it or is it not possible (Python 3.7)? What I have in mind is basically

some_number = 0.3140
string = f'{some_number:x}' # giving '.314'

that gives the output string '.314'.. So is there an x that does this?

Of course one could work-around with lstrip / rstrip as described e.g. here or similar here:

In [93]: str(0.3140).lstrip('0').rstrip('0')
Out[93]: '.314'

but it would be more convenient to use only an f-string. Since I can use that for other formatting options, optionally calling strip demands additional lines of code.

4
@gpk, I am NOT looking for a strip method. I made an edit to clarify. - MrFuppes
oh, alright @MrFuppes, maybe this can help - stackoverflow.com/questions/10303797/… - gpk27
@gpk27, thanks, but I looked into the answers that were given in the Q&A you suggested. Seems to be another hack; defining new classes it not what I have in mind. - MrFuppes
I don't know if this fits your requirement, but you can combine f-strings with the strip() methods by using string = f'{(str(some_number).lstrip("0").rstrip("0"))}' . - Jack Fleeting

4 Answers

1
votes

just to mention it here... if you use numpy there's also the function np.format_float_positional() that gives you full control of how to display numbers as strings and trim trailing zeros...

from the doc of np.format_float_positional:

Format a floating-point scalar as a decimal string in positional notation.

Provides control over rounding, trimming and padding. Uses and assumes IEEE >unbiased rounding. Uses the "Dragon4" algorithm.

getting rid of the leading zero is then just a simple check whether we're dealing with a number that starts with 0 or not

import numpy as np
def format_float(x, trim_leading=True, **kwargs):
    s = np.format_float_positional(x, **kwargs)
    if trim_leading is True and int(x) == 0 and len(s) > 1:
        s = s.replace("0.", ".")
    return s
format_float(0.0234001232, trim_leading=True, precision=4)
>>> '.0234'
format_float(0.0234001232, trim_leading=False, precision=4)
>>> '0.0234'
format_float(0.0234001232, precision=8)
>>> '0.02340012'
format_float(12.000558, precision=2, trim="-", fractional=False)
>>> '12'
0
votes

if you want to just strip 0 from floating numbers you could use this "hack"

"." + str(0.314).split("0.")[-1]

this is in no way an elegant solution, but it will get the job done

also if you want to use .format as well you don't need another line, you could just

"." +str(0.314).split("0.")[-1].format('')
0
votes

If you want to use format(), then try as below.

print("Hello {0}, your balance is {1}.".format("Adam", "0.314".lstrip('0')))

Just use lstrip() within format function, you don't need to write additional line of code.

0
votes

here's a helper function that I came up with since the strip workaround can't be avoided:

def dec2string_stripped(num, dec_places=3, strip='right'):
    """
    Parameters
    ----------
    num : float or list of float
        scalar or list of decimal numbers.
    dec_places : int, optional
        number of decimal places to return. defaults to 3.
    strip : string, optional
        what to strip. 'right' (default), 'left' or 'both'.

    Returns
    -------
    list of string.
        numbers formatted as strings according to specification (see kwargs).
    """
    if not isinstance(num, list): # might be scalar or numpy array
        try:
            num = list(num)
        except TypeError: # input was scalar
            num = [num]

    if not isinstance(dec_places, int) or int(dec_places) < 1:
        raise ValueError(f"kwarg dec_places must be integer > 1 (got {dec_places})")

    if strip == 'right':
        return [f"{n:.{str(dec_places)}f}".rstrip('0') for n in num]
    if strip == 'left':
        return [f"{n:.{str(dec_places)}f}".lstrip('0') for n in num]
    if strip == 'both':
        return [f"{n:.{str(dec_places)}f}".strip('0') for n in num]
    raise ValueError(f"kwarg 'strip' must be 'right', 'left' or 'both' (got '{strip}')")