打印浮点值而不导致零

Pau*_*eeb 34 python string-formatting

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

问题

>>> k = .1337
>>> print "%.4f" % k
'0.1337'
Run Code Online (Sandbox Code Playgroud)

>>> print ("%.4f" % k) [1:]
'.1337'
Run Code Online (Sandbox Code Playgroud)

NPE*_*NPE 30

这是另一种方式:

>>> ("%.4f" % k).lstrip('0')
'.1337'
Run Code Online (Sandbox Code Playgroud)

它略胜一筹[1:],因为它也适用于数> = 1.

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

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

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

  • 这里的正则表达式对于绝对值大于10且在某个位置具有零的数字将无法正常工作.例如,100.1337变为10.1337. (3认同)
  • @musicinmybrain 你应该用那个正则表达式写出你自己的答案 (2认同)

jre*_*nie 9

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

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'
Run Code Online (Sandbox Code Playgroud)

这有利于易于理解,部分原因startswith是简单的字符串匹配而不是正则表达式.


Pau*_*eeb 6

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

k = -.1337
("%.4f" % k).replace("-0","-").lstrip("0")
Run Code Online (Sandbox Code Playgroud)


A.J*_*pal 5

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

\n
>>> k = .1827412\n>>> print ("%.4f"%(k)).lstrip(\'0\')\n.1827\n>>> \n
Run Code Online (Sandbox Code Playgroud)\n

.lstrip()可用于删除字符串的任何前导字符:

\n
>>> k = \'bhello\'\n>>> print k.lstrip(\'b\')\nhello\n>>> print k.lstrip(\'bhel\')\no\n>>> print k.lstrip(\'bel\')\nhello\n>>> \n
Run Code Online (Sandbox Code Playgroud)\n

来自文档

\n
\n

string.lstrip(s[, 字符])

\n

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

\n
\n


Deb*_*ndu 5

您可以使用以下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)
Run Code Online (Sandbox Code Playgroud)

使用此类,您必须使用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
Run Code Online (Sandbox Code Playgroud)

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

[注意:以上所有代码都是用Python3编写的.您还必须__unicode__在Python2中覆盖并且还必须更改super调用.]

PS:您也可以覆盖__repr__类似的方法__str__,如果您还想更改官方字符串表示形式MyFloat.




编辑:实际上你可以添加新的语法来使用__format__方法格式化sting .因此,如果您想要保持两种行为,即在需要时显示前导零,并且在不需要时不显示前导零.您可以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
Run Code Online (Sandbox Code Playgroud)

并使用此类如下:

>>> 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
Run Code Online (Sandbox Code Playgroud)

请注意,使用'fz'而不是'f'会删除前导零.

此外,上面的代码适用于Python2和Python3.

  • 这是我的(*不公平/不现实*)测试用例,它产生了一个错误的答案:`'.402''replace('0','',1)` - >`.42`.你的代码适用于当前定义的`float`上`__str__`生成的所有字符串,但你的代码很脆弱(笨重).它不是幂等的.而且它不是面向未来的.`lstrip`更加简洁和强大(幂等和面向未来).您的`replace`操作无法多次应用.如果您的特定数字类型没有字符串化python内置浮动的方式,那么...... (2认同)