Print floating point values without leading zero

后端 未结 13 1211
逝去的感伤
逝去的感伤 2020-11-30 05:21

Trying to use a format specifier to print a float that will be less than 1 without the leading zero. I came up with a bit of a hack but I assume there is a way to just drop

13条回答
  •  情话喂你
    2020-11-30 06:12

    You may use the following MyFloat class instead of the builtin float class.

    def _remove_leading_zero(value, string):
        if 1 > value > -1:
            string = string.replace('0', '', 1)
        return string
    
    
    class MyFloat(float):
        def __str__(self):
            string = super().__str__()
            return _remove_leading_zero(self, string)
    
        def __format__(self, format_string):
            string = super().__format__(format_string)
            return _remove_leading_zero(self, string)
    

    Using this class you'll have to use str.format function instead of the modulus operator (%) for formatting. Following are some examples:

    >>> print(MyFloat(.4444))
    .4444
    
    >>> print(MyFloat(-.4444))
    -.4444
    
    >>> print('some text {:.3f} some more text',format(MyFloat(.4444)))
    some text .444 some more text
    
    >>> print('some text {:+.3f} some more text',format(MyFloat(.4444)))
    some text +.444 some more text
    

    If you also want to make the modulus operator (%) of str class to behave the same way then you'll have to override the __mod__ method of str class by subclassing the class. But it won't be as easy as overriding the __format__ method of float class, as in that case the formatted float number could be present at any position in the resultant string.

    [Note: All the above code is written in Python3. You'll also have to override __unicode__ in Python2 and also have to change the super calls.]

    P.S.: You may also override __repr__ method similar to __str__, if you also want to change the official string representation of MyFloat.




    Edit: Actually you can add new syntax to format sting using __format__ method. So, if you want to keep both behaviours, i.e. show leading zero when needed and don't show leading zero when not needed. You may create the MyFloat class as follows:

    class MyFloat(float):
        def __format__(self, format_string):
            if format_string.endswith('z'):  # 'fz' is format sting for floats without leading the zero
                format_string = format_string[:-1]
                remove_leading_zero = True
            else:
                remove_leading_zero = False
    
            string = super(MyFloat, self).__format__(format_string)
            return _remove_leading_zero(self, string) if remove_leading_zero else string
            # `_remove_leading_zero` function is same as in the first example
    

    And use this class as follows:

    >>> print('some text {:.3f} some more text',format(MyFloat(.4444)))
    some text 0.444 some more text
    >>> print('some text {:.3fz} some more text',format(MyFloat(.4444)))
    some text .444 some more text
    
    
    >>> print('some text {:+.3f} some more text',format(MyFloat(.4444)))
    some text +0.444 some more text
    >>> print('some text {:+.3fz} some more text',format(MyFloat(.4444)))
    some text +.444 some more text
    
    
    >>> print('some text {:.3f} some more text',format(MyFloat(-.4444)))
    some text -0.444 some more text
    >>> print('some text {:.3fz} some more text',format(MyFloat(-.4444)))
    some text -.444 some more text
    

    Note that using 'fz' instead of 'f' removes the leading zero.

    Also, the above code works in both Python2 and Python3.

提交回复
热议问题