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
A super short (although not very pythonic) one-liner, which also handles negative numbers:
k = -.1337
"-"*(k<0)+("%.4f"%abs(k)).lstrip('0')
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.
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.', '.')
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.
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')))
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.