打印浮点值而不导致零

时间:2012-04-24 18:24:22

标签: python string-formatting

尝试使用格式说明符打印一个小于1而没有前导零的浮点数。我想出了一些黑客,但我认为有一种方法可以在格式说明符中删除前导零。我在文档中找不到它。

问题

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

哈克

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

13 个答案:

答案 0 :(得分:30)

这是另一种方式:

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

它比[1:]更为通用,因为它也适用于数字> = 1。

但是,这两种方法都没有正确处理负数。在这方面,以下情况更好:

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

不是特别优雅,但现在我想不出更好的方法。

答案 1 :(得分:8)

尽管我喜欢可爱的正则表达式技巧,但我认为直接的功能是最好的方法:

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'

这样做的好处是易于理解,部分原因是startswith是一个简单的字符串匹配而不是正则表达式。

答案 2 :(得分:6)

一个可行的选项,没有正则表达式,负数大于10

k = -.1337
("%.4f" % k).replace("-0","-").lstrip("0")

答案 3 :(得分:4)

import re
re.sub("^(\-?)0\.", r'\1.', "%.4f" % k)

这很简单,我无法找到一个不起作用的场景。

示例:

>>> 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'

修改: 如果您只考虑数字> -10和< 10以下内容将起作用:

("%.4f", k).replace('0.', '.')

答案 4 :(得分:4)

更倾向于阅读和简单:让我们独立处理标志和数字。如果声明永远不会伤害任何人,那么有点内联。

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

答案 5 :(得分:4)

使用字符串格式转换为字符串后使用.lstrip()

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

.lstrip()可用于删除字符串中的任何主要字符:

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

From the docs

  

string.lstrip(s [,chars])

     

返回删除了前导字符的字符串副本

答案 6 :(得分:4)

您可以使用以下MyFloat课程代替内置float课程。

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)

使用此类,您必须使用str.format函数而不是模数运算符(%)进行格式化。以下是一些例子:

>>> 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

如果您还想使%类的模数运算符(str)的行为方式相同,那么您必须覆盖__mod__ str方法1}}通过继承类的类。但它不会像覆盖__format__类的float方法一样容易,因为在这种情况下,格式化的浮点数可能出现在结果字符串中的任何位置。

[注意:以上所有代码都是用Python3编写的。 您还必须覆盖Python2中的__unicode__ ,还必须更改super来电。]

P.S。:如果您还想更改__repr__的{​​{3}},也可以覆盖类似于__str__的{​​{1}}方法。




修改:实际上,您可以使用MyFloat方法添加新语法来格式化sting。因此,如果你想保持这两种行为,即在需要时显示前导零并且在不需要时不显示前导零。您可以按如下方式创建__format__类:

MyFloat

使用此课程如下:

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

请注意使用&#39; fz&#39;而不是&#39; f&#39;删除前导零。

此外,上述代码适用于Python2和Python3。

答案 7 :(得分:2)

因为我们只考虑&gt; -1到&lt; 1然后以下编辑将起作用。

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

这将保持符号,只删除小数点左边的数字。

答案 8 :(得分:2)

我很惊讶没有人提出更多数学方法来做到这一点:

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

对我来说看起来更好。 :)

但有趣的是你的速度最快。

$ 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

答案 9 :(得分:1)

Python的标准lib的str.format()可用于生成float值的字符串转换。然后可以操纵该字符串以形成正数或负数的最终结果。

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

答案 10 :(得分:0)

对于Python 3

当您需要简单的东西并且不需要负数支持时:

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

当您需要负数支持时,还有其他解决方案,包括@ nettux443提供的出色正则表达式。

答案 11 :(得分:0)

一个超短(尽管不是很Pythonic)的单行代码,它也处理负数:

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

答案 12 :(得分:0)

问题是打印浮点数时不带前导零。前导零始终位于小数点之前。将打印的浮点数拆分为“ 0.”,然后仅在“。”附近重新加入结果列表,如下所示:

>> flt = -.31415926

-0.31415926

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

'-0.3142'

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

'-。3142'