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

Tar*_*rGz 161 python floating-point formatting pretty-print

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

喜欢:

3 -> "3"
3. -> "3"
3.0 -> "3"
3.1 -> "3.1"
3.14 -> "3.14"
3.140 -> "3.14"
Run Code Online (Sandbox Code Playgroud)

Ale*_*lli 166

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

  • 唯一的问题是`'%.2f'%-0.0001`将为您留下`-0.00`并最终为'-0`. (4认同)
  • @ alexanderlukanin13因为默认精度为6,请参阅https://docs.python.org/2/library/string.html:`'f'固定点.将数字显示为定点数.默认精度为6.`您必须在上述解决方案中使用'%0.7f'. (3认同)
  • @derenio好点:-)我只能补充说,提高''%0.15f'以上的精度是一个坏主意,因为[奇怪的东西](https://en.wikipedia.org/wiki/IEEE_floating_point)开始发生. (3认同)
  • @GabrielStaples 这将删除小数点之前出现的零。我认为这是因为“.”是一个通配符,将匹配单个字符。 (3认同)
  • 如果你在其他字符串的中间:`print('In the middle {} and something else'.format('{:f}'.format(a).rstrip('0')))` (2认同)
  • @Alex Martelli,摆脱双重“rstrip”命令。只需使用此选项即可在一次操作中去除点 (`.`) 和所有尾随零:`('%f' % x).rstrip('.0')` (2认同)
  • @Peter Schorn:你说得对,Gabriel Staples 的优化很糟糕,但这是因为 OP 的技巧要求你删除所有零,然后删除所有小数,然后不再删除零。加布里埃尔的方法只是删除所有零和句点,直到遇到其他内容。 (2认同)

unu*_*tbu 133

你可以%g用来实现这个目标:

'%g'%(3.140)
Run Code Online (Sandbox Code Playgroud)

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

'{0:g}'.format(3.140)
Run Code Online (Sandbox Code Playgroud)

来自以下文档format:g原因(除其他外)

从有效数字中删除无关紧要的尾随零,如果后面没有剩余数字,也会删除小数点.

  • 哦,差不多!有时它以科学记数法("2.342E + 09")格式化浮点数 - 是否可以将其关闭,即始终显示所有有效数字? (25认同)
  • 在 Python 3.6 中,可以缩写为 `f"{var:g}"`,其中 `var` 是浮点变量。 (8认同)
  • 为什么使用`'{0:...}'.format(value)`当你可以使用`format(value,'...')`?这避免了必须从模板字符串中解析出格式说明符,否则该模板字符串为空. (5认同)
  • @MartijnPieters:解析格式说明符的微小成本被其他开销的AFAICT所淹没;在实践中,我在3.6上的本地基准测试(具有微基准的功能作用域以准确地对真实代码进行建模)具有`format(v,'2.5f')`比`'{:2.5f}'.. format( v)`。即使没有,我也倾向于使用“ str”方法形式,因为当我需要对其进行调整,向其添加其他值等时,更改的内容很少。当然,从3.6版本开始,我们可以将f字符串用于大多数用途。:-) (2认同)

And*_*der 12

尝试最简单,最有效的方法怎么样?normalize()方法删除所有最右边的尾随零.

from decimal import Decimal

print (Decimal('0.001000').normalize())
# Result: 0.001
Run Code Online (Sandbox Code Playgroud)

适用于Python 2Python 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()
Run Code Online (Sandbox Code Playgroud)

  • 除了Decimal('10 .0')。normalize()`变为'1E + 1'` (2认同)

Pol*_*esh 10

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

def floatToString(inputValue):
    return ('%.15f' % inputValue).rstrip('0').rstrip('.')
Run Code Online (Sandbox Code Playgroud)

我的推理:

%g 没有摆脱科学记数法.

>>> '%g' % 0.000035
'3.5e-05'
Run Code Online (Sandbox Code Playgroud)

15个小数位似乎可以避免奇怪的行为,并且对我的需求有很大的精确度.

>>> ('%.15f' % 1.35).rstrip('0').rstrip('.')
'1.35'
>>> ('%.16f' % 1.35).rstrip('0').rstrip('.')
'1.3500000000000001'
Run Code Online (Sandbox Code Playgroud)

我可以使用format(inputValue, '.15f').而不是'%.15f' % inputValue,但这有点慢(~30%).

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

>>> Decimal('0.21000000000000000000000000006').normalize()
Decimal('0.2100000000000000000000000001')
>>> Decimal('0.21000000000000000000000000006')
Decimal('0.21000000000000000000000000006')
Run Code Online (Sandbox Code Playgroud)

最重要的是,我仍然会转而Decimal使用float能够让你最终得到的东西,而不是你放在那里的数字.Decimal当算术保持在Decimal并且Decimal用字符串初始化时,我认为效果最好.

>>> Decimal(1.35)
Decimal('1.350000000000000088817841970012523233890533447265625')
>>> Decimal('1.35')
Decimal('1.35')
Run Code Online (Sandbox Code Playgroud)

我确定Decimal.normalize()可以使用上下文设置调整精度问题,但考虑到已经很慢的速度并且不需要荒谬的精度,而且我仍然会从浮动转换并且无论如何都会失去精度,我没有我认为值得追求.

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

def floatToString(inputValue):
    result = ('%.15f' % inputValue).rstrip('0').rstrip('.')
    return '0' if result == '-0' else result
Run Code Online (Sandbox Code Playgroud)

  • 不幸的是,仅适用于小数点左侧少于大约五位或更多位的数字。例如,“floatToString(12345.6)”返回“12345.600000000000364”。在本例中,将“%.15f”中的 15 减少到一个较小的数字可以解决这个问题,但随着数字变大,该值需要越来越小。它可以根据数字的 log-base-10 动态计算,但这很快就会变得非常复杂。 (3认同)
  • 解决该问题的一种方法可能是限制整数的长度(而不仅仅是小数点后的数字):`result = ('%15f' % val).rstrip('0').rstrip('. ').lstrip(' ')` (2认同)
  • @JohnSpieks 我不确定这是可以避免的。这是浮点数的副作用,如果左边需要更多的数字,就无法代表精度。据我所知,作为字符串输出的数字与作为浮点数输入的数字相同,或者至少是最接近的表示形式。`>>>12345.600000000000364 == 12345.6``正确` (2认同)

Kau*_*odi 6

这是一个对我有用的解决方案。这是一个混合的解决方案通过多网并使用新的.format() 语法

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

输出

3
3
3
3.1
3.14
3.14
Run Code Online (Sandbox Code Playgroud)

  • 添加到 beruic 的评论中,这不适用于更高精度的浮点数(例如“3.141”),因为“.2f”是硬编码的。 (2认同)
  • result = "{:.{}f}".format(float(format(number).rstrip('0').rstrip('.')), precision),修复了 TrebledJ 的问题。 (2认同)
  • 非常适合单行一次使用的应用程序,无需额外的库 (2认同)

Yur*_*uri 6

如果您想要同时适用于数字或字符串输入的东西(感谢@mike-placentra 寻找错误):

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

  • 这不适用于“num(30)”(->“3”) (3认同)

cle*_*lel 5

您可以简单地使用 format() 来实现这一点:

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

  • `格式(30000000000, '.10g')` -> `3e+10` (6认同)

归档时间:

查看次数:

98373 次

最近记录:

6 年,4 月 前