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

例如:

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

当前回答

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

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')。而不是'%。inputValue,但这有点慢(~30%)。

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

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

最重要的是,我仍然会从浮点数转换为十进制,这可能会让你得到其他东西,而不是你在那里输入的数字。我认为十进制工作最好时,算术保持在十进制和十进制初始化的字符串。

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

其他回答

以下是答案:

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和小数。

虽然格式化可能是最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的详细信息。

你可以用最python的方式来实现:

python3:

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

如果你能接受3个。3.0以“3.0”的形式出现,这是一种非常简单的方法,从浮点数表示中右移零:

print("%s"%3.140)

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

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

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')。而不是'%。inputValue,但这有点慢(~30%)。

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

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

最重要的是,我仍然会从浮点数转换为十进制,这可能会让你得到其他东西,而不是你在那里输入的数字。我认为十进制工作最好时,算术保持在十进制和十进制初始化的字符串。

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