格式化Python中的浮点数而没有多余的零

时间:2010-03-14 00:27:39

标签: python formatting floating-point pretty-print

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

像:

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

20 个答案:

答案 0 :(得分:157)

我,我会做('%f' % x).rstrip('0').rstrip('.') - 保证定点格式而不是科学记法等等。是的,不像%g那样光滑和优雅,但是,它有效(而且我不知道如何强迫%g永远不要使用科学记数法; - )。

答案 1 :(得分:121)

您可以使用%g来实现此目标:

'%g'%(3.140)

或者,对于Python 2.6或更高版本:

'{0:g}'.format(3.140)

来自docs for formatg原因(以及其他内容)

  

无关紧要的尾随零[将]   从有效数字中删除,然后删除   如果有,小数点也被删除   在它之后没有剩余的数字。

答案 2 :(得分:11)

尝试最简单且最有效的方法怎么样? 方法 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()

答案 3 :(得分:10)

在查看几个类似问题的答案后,这对我来说似乎是最好的解决方案:

def floatToString(inputValue):
    return ('%.15f' % inputValue).rstrip('0').rstrip('.')

我的推理:

%g并没有摆脱科学记数法。

>>> '%g' % 0.000035
'3.5e-05'

15个小数位似乎可以避免出现奇怪的行为,并且能够满足我的需求。

>>> ('%.15f' % 1.35).rstrip('0').rstrip('.')
'1.35'
>>> ('%.16f' % 1.35).rstrip('0').rstrip('.')
'1.3500000000000001'

我本可以使用format(inputValue, '.15f').代替'%.15f' % inputValue,但这有点慢(约30%)。

我本可以使用Decimal(inputValue).normalize(),但这也有一些问题。首先,它慢了很多(~11x)。我还发现虽然它具有非常高的精度,但在使用normalize()时仍然会出现精度损失。

>>> Decimal('0.21000000000000000000000000006').normalize()
Decimal('0.2100000000000000000000000001')
>>> Decimal('0.21000000000000000000000000006')
Decimal('0.21000000000000000000000000006')

最重要的是,我仍然会从Decimal转换为float,这会让你最终得到的东西不是你放在那里的数字。我认为Decimal在算术停留在Decimal并且Decimal用字符串初始化时效果最佳。

>>> Decimal(1.35)
Decimal('1.350000000000000088817841970012523233890533447265625')
>>> Decimal('1.35')
Decimal('1.35')

我确定可以使用上下文设置将Decimal.normalize()的精度问题调整为所需的,但考虑到已经很慢的速度并且不需要荒谬的精确度以及我仍然保持这样的事实无论如何,从浮动和失去精度转换,我认为这不值得追求。

我并不关心可能的" -0"结果,因为-0.0是一个有效的浮点数,无论如何它可能是罕见的,但既然你提到你想保持字符串结果尽可能短,你可以总是使用额外的条件,只需很少的额外速度成本

def floatToString(inputValue):
    result = ('%.15f' % inputValue).rstrip('0').rstrip('.')
    return '0' if result == '-0' else result

答案 4 :(得分:5)

这是一个适合我的解决方案。它是solution PolyMesh 的混合,并使用了新的.format() syntax

for num in 3, 3., 3.0, 3.1, 3.14, 3.140:
    print('{0:.2f}'.format(num).rstrip('0').rstrip('.'))

<强>输出

3
3
3
3.1
3.14
3.14

答案 5 :(得分:2)

虽然格式化可能是大多数Pythonic方式,但这是使用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

答案 6 :(得分:2)

您只需使用format()即可实现此目的:

format(3.140, '.10g')其中10是您想要的精度。

答案 7 :(得分:1)

>>> str(a if a % 1 else int(a))

答案 8 :(得分:1)

如果您可以使用3.和3.0显示为“3.0”,这是一种非常简单的方法,可以从浮点表示中删除零:

print("%s"%3.140)

(感谢@ellimilial指出例外情况)

答案 9 :(得分:1)

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

在这种情况下,它将不使用电子符号:

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

答案 10 :(得分:1)

这是答案:

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='-'会删除尾随的零和小数点。

答案 11 :(得分:0)

对于浮动你可以使用它:

>>> format_float(1.00000)
'1'
>>> format_float(1.1234567890000000000)
'1.123456789'

测试它:

string SIDsubresult = subresult;
    SIDsubresult = SIDsubresult.Replace(".", "");
    string SIDresult = result;
    SIDresult = SIDresult.Replace(".", "");
    long iSIDs = Convert.ToInt64(SIDsubresult);
    long iSIDr = Convert.ToInt64(SIDresult);
    Console.Write(iSIDr & iSIDs);

对于十进制,请在此处查看解决方案:https://stackoverflow.com/a/42668598/5917543

答案 12 :(得分:0)

OP希望删除超级零,并使得结果字符串尽可能短。

我发现%g指数格式化会缩短非常大和非常小的值的结果字符串。问题出现在不需要指数表示法的值上,如128.0,它既不是很大也不是很小。

这是将数字格式化为短字符串的一种方法,仅当Decimal.normalize创建太长的字符串时才使用%g指数表示法。这可能不是最快的解决方案(因为它确实使用了Decimal.normalize)

def floatToString (inputValue, precision = 3):
    rc = str(Decimal(inputValue).normalize())
    if 'E' in rc or len(rc) > 5:
        rc = '{0:.{1}g}'.format(inputValue, precision)        
    return rc

inputs = [128.0, 32768.0, 65536, 65536 * 2, 31.5, 1.000, 10.0]

outputs = [floatToString(i) for i in inputs]

print(outputs)

# ['128', '32768', '65536', '1.31e+05', '31.5', '1', '10']

答案 13 :(得分:0)

处理%f,您应该输入

  

%。2f

,其中: .2f == .00浮点数。

示例:

打印“价格:%。2f”%价格[产品]

输出:

价格:1.50

答案 14 :(得分:0)

试试这个,它会允许你添加一个“精度”变量来设置你想要的小数位数。只要记住它会四舍五入。请注意,这仅在字符串中有小数时才有效。

 number = 4.364004650000000
 precision = 2
 result = "{:.{}f}".format(float(format(number).rstrip('0').rstrip('.')), precision)

输出

 4.364004650000000
 4.36

答案 15 :(得分:0)

如果你想要一些既适用于数字输入又适用于字符串输入的东西:

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

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

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

答案 16 :(得分:-1)

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

编辑:它不起作用

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

答案 17 :(得分:-1)

您可以像这样使用max()

print(max(int(x), x))

答案 18 :(得分:-1)

"{:.5g}".format(x)

我用它来格式化浮点数以尾随零。

答案 19 :(得分:-3)

你可以用大多数pythonic方式实现这一点:

python3:

"{:0.0f}".format(num)