我如何格式化一个浮点数,使它不包含尾随零?换句话说,我希望得到的字符串尽可能短。

例如:

3 -> "3"
3. -> "3"
3.0 -> "3"
3.1 -> "3.1"
3.14 -> "3.14"
3.140 -> "3.14"

当前回答

以下是答案:

import numpy

num1 = 3.1400
num2 = 3.000
numpy.format_float_positional(num1, 3, trim='-')
numpy.format_float_positional(num2, 3, trim='-')

输出“3.14”和“3”

Trim ='-'删除后面的0和小数。

其他回答

试试最简单、可能也是最有效的方法怎么样? normalize()方法删除所有最右边的尾随零。

from decimal import Decimal

print (Decimal('0.001000').normalize())
# Result: 0.001

适用于Python 2和Python 3。

——更新——

正如@BobStein-VisiBone指出的那样,唯一的问题是,像10,100,1000这样的数字……将以指数形式显示。使用下面的函数可以很容易地解决这个问题:

from decimal import Decimal


def format_float(f):
    d = Decimal(str(f));
    return d.quantize(Decimal(1)) if d == d.to_integral() else d.normalize()

虽然格式化可能是最python的方式,但这里有一个使用more_itertools的替代解决方案。rstrip工具。

import more_itertools as mit


def fmt(num, pred=None):
    iterable = str(num)
    predicate = pred if pred is not None else lambda x: x in {".", "0"}
    return "".join(mit.rstrip(iterable, predicate))


assert fmt(3) == "3"
assert fmt(3.) == "3"
assert fmt(3.0) == "3"
assert fmt(3.1) == "3.1"
assert fmt(3.14) == "3.14"
assert fmt(3.140) == "3.14"
assert fmt(3.14000) == "3.14"
assert fmt("3,0", pred=lambda x: x in set(",0")) == "3"

数字被转换为字符串,该字符串去掉了满足谓词的尾随字符。函数定义fmt不是必需的,但是这里用它来测试断言,断言都通过了。注意:它适用于字符串输入并接受可选谓词。

另请参阅第三方库more_itertools的详细信息。

使用QuantiPhy包是一种选项。通常QuantiPhy用于 使用数字单位和SI比例因子,但它有各种 不错的数字格式选项。

    >>> from quantiphy import Quantity

    >>> cases = '3 3. 3.0 3.1 3.14 3.140 3.14000'.split()
    >>> for case in cases:
    ...    q = Quantity(case)
    ...    print(f'{case:>7} -> {q:p}')
          3 -> 3
         3. -> 3
        3.0 -> 3
        3.1 -> 3.1
       3.14 -> 3.14
      3.140 -> 3.14
    3.14000 -> 3.14

在这种情况下,它不会使用e符号:

    >>> cases = '3.14e-9 3.14 3.14e9'.split()
    >>> for case in cases:
    ...    q = Quantity(case)
    ...    print(f'{case:>7} -> {q:,p}')
    3.14e-9 -> 0
       3.14 -> 3.14
     3.14e9 -> 3,140,000,000

您可能更喜欢的另一种选择是使用SI比例因子,可能带有单位。

    >>> cases = '3e-9 3.14e-9 3 3.14 3e9 3.14e9'.split()
    >>> for case in cases:
    ...    q = Quantity(case, 'm')
    ...    print(f'{case:>7} -> {q}')
       3e-9 -> 3 nm
    3.14e-9 -> 3.14 nm
          3 -> 3 m
       3.14 -> 3.14 m
        3e9 -> 3 Gm
     3.14e9 -> 3.14 Gm

如果你想要一些既适用于数字输入又适用于字符串输入的东西(感谢@mike-placentra的bug搜索):

def num(s):
    """ 3.0 -> 3, 3.001000 -> 3.001 otherwise return s """
    s = str(s)
    try:
        int(float(s))
        if '.' not in s:
            s += '.0'
        return s.rstrip('0').rstrip('.')
    except ValueError:
        return s

>>> for n in [3, 3., 3.0, 3.1, 3.14, 3.140, 3.001000, 30 ]: print(num(n))
... 
3
3
3
3.1
3.14
3.14
3.001
30

>>> for n in [3, 3., 3.0, 3.1, 3.14, 3.140, 3.001000, 30 ]: print(num(str(n)))
... 
3
3
3
3.1
3.14
3.14
3.001
30

使用宽度足够大的%g,例如'%.99g'。 它将以定点符号打印任何相当大的数字。

编辑:它不起作用

>>> '%.99g' % 0.0000001
'9.99999999999999954748111825886258685613938723690807819366455078125e-08'