Print floating point values without leading zero

Question:

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 the leading zero in the format specifier. I couldn’t find it in the docs.

Issue

>>> k = .1337
>>> print "%.4f" % k
'0.1337'

Hack

>>> print ("%.4f" % k) [1:]
'.1337'
Asked By: Paul Seeb

||

Answers:

Here is another way:

>>> ("%.4f" % k).lstrip('0')
'.1337'

It is slightly more general than [1:] in that it also works with numbers >=1.

Neither method correctly handles negative numbers, however. The following is better in this respect:

>>> re.sub('0(?=[.])', '', ("%0.4f" % -k))
'-.1337'

Not particularly elegant, but right now I can’t think of a better method.

Answered By: NPE

One viable option which works without regex and with negative numbers greater than 10

k = -.1337
("%.4f" % k).replace("-0","-").lstrip("0")
Answered By: Paul Seeb

Since we’re only considering > -1 to < 1 then the following edit will work.

import re
re.sub(r"0+.", ".", %0.4f" % k)

This will maintain the sign, only removing the digit to the left of the decimal.

Answered By: NanoBennett

As much as I like cute regex tricks, I think a straightforward function is the best way to do this:

def formatFloat(fmt, val):
  ret = fmt % val
  if ret.startswith("0."):
    return ret[1:]
  if ret.startswith("-0."):
    return "-" + ret[2:]
  return ret

>>> formatFloat("%.4f", .2)
'.2000'
>>> formatFloat("%.4f", -.2)
'-.2000'
>>> formatFloat("%.4f", -100.2)
'-100.2000'
>>> formatFloat("%.4f", 100.2)
'100.2000'

This has the benefit of being easy to understand, partially because startswith is a simple string match rather than a regex.

Answered By: jrennie
import re
re.sub("^(-?)0.", r'1.', "%.4f" % k)

This is short, simple and I can’t find a scenario for which it doesn’t work.

Examples:

>>> import re
>>> re.sub("^(-?)0.", r'1.', "%.4f" % 0)
'.0000'
>>> re.sub("^(-?)0.", r'1.', "%.4f" % 0.1337)
'.1337'
>>> re.sub("^(-?)0.", r'1.', "%.4f" % 1.337)
'1.3370'
>>> re.sub("^(-?)0.", r'1.', "%.4f" % -0)
'.0000'
>>> re.sub("^(-?)0.", r'1.', "%.4f" % -0.1337)
'-.1337'
>>> re.sub("^(-?)0.", r'1.', "%.4f" % -1.337)
'-1.3370'
>>> re.sub("^(-?)0.", r'1.', "%.4f" % 10.337)
'10.3370'
>>> re.sub("^(-?)0.", r'1.', "%.4f" % -10.337)
'-10.3370'

Edit:
If you are only considering numbers > -10 and < 10 The following will work:

("%.4f", k).replace('0.', '.')
Answered By: nettux

I’d rather go for readable and simple than anything else: Let’s handle the sign and the numerics independently. And a little in-line if statement never hurt anyone.

k = -.1337
"".join( ["-" if k < 0 else "", ("%.4f" % abs(k)).lstrip('0')] )
Answered By: John Haberstroh

Use .lstrip(), after using string formatting to convert to a string:

>>> k = .1827412
>>> print ("%.4f"%(k)).lstrip('0')
.1827
>>> 

.lstrip() can be used to remove any of the leading characters of a string:

>>> k = 'bhello'
>>> print k.lstrip('b')
hello
>>> print k.lstrip('bhel')
o
>>> print k.lstrip('bel')
hello
>>> 

From the docs:

string.lstrip(s[, chars])

        Return a copy of the string with leading characters removed

Answered By: A.J. Uppal

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.

Answered By: Debanshu Kundu

Python’s standard lib’s str.format() can be used to generate the string conversion of the float value. Then the string can be manipulated to form a final result for either a positive or negative number.

n = -.1234567890
print('{0}'.format('-' if n < 0 else '') + ('{:0.4}'.format(n).split('-')[1 if n < 0 else 0].lstrip('0')))
Answered By: StormCrow

I am surprised nobody suggested a more mathematical way to do it:

n = 0.123456789
'.%d' % (n*1e4)

Looks much nicer to me. 🙂

But interestingly yours is the fastest.

$ python -mtimeit '".%d" % (0.123456789*1e4)'
1000000 loops, best of 3: 0.809 usec per loop
$ python -mtimeit '("%.4f"%(0.123456789)).lstrip("0")'
1000000 loops, best of 3: 0.209 usec per loop
$ python -mtimeit '("%.4f"%(0.123456789))[1:]'
10000000 loops, best of 3: 0.0723 usec per loop

For Python 3

When you want something simple and don’t need negative number support:

f'{k:.4f}'.lstrip('0')

There are other solutions when you need negative number support, including the excellent regex by @nettux443.

Answered By: Brent Faust

A super short (although not very pythonic) one-liner, which also handles negative numbers:

k = -.1337
"-"*(k<0)+("%.4f"%abs(k)).lstrip('0')
Answered By: hgzech

The problem is to print a float without the leading zero, regardless of the sign of the float. The leading zero always precedes a decimal point. Split the printed float on ‘0.’, and then rejoin the resulting list around just ‘.’, as in below:

>> flt = -.31415926

-0.31415926

>> '%.4f' % flt    # prints leading zero

‘-0.3142’

>> '.'.join( ('%.4f' % flt).split('0.'))    # removes leading zero

‘-.3142’

Answered By: Steven Rosenthal
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.