Search code examples
pythonstringformatf-string

Number to string conversion with f-string without leading or trailing zeros?


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.


Solution

  • 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}')")