格式化浮点数去除尾随零
我想知道怎么把一个浮点数格式化成没有多余零的样子。换句话说,我希望得到的字符串尽可能简短。
比如:
3 -> "3"
3. -> "3"
3.0 -> "3"
3.1 -> "3.1"
3.14 -> "3.14"
3.140 -> "3.14"
19 个回答
看了几个类似问题的回答后,我觉得这个方案对我来说是最好的:
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()
,但这也有一些问题。首先,它慢得多(大约慢11倍)。我发现虽然它的精度很高,但在使用 normalize()
时仍然会有精度损失。
>>> Decimal('0.21000000000000000000000000006').normalize()
Decimal('0.2100000000000000000000000001')
>>> Decimal('0.21000000000000000000000000006')
Decimal('0.21000000000000000000000000006')
最重要的是,我还是要把 float
转换成 Decimal
,这可能会导致你得到的结果和你输入的不一样。我觉得 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
你可以用 %g
来实现这个效果:
'%g'%(3.140)
或者,如果你使用的是 Python 版本大于等于 2.6:
'{0:g}'.format(3.140)
或者,如果你使用的是 Python 版本大于等于 3.6:
f'{3.140:g}'
根据 format 的文档,g
的作用是:
会把不重要的尾随零去掉,同时如果小数点后面没有数字,小数点也会被去掉。
我会用 ('%f' % x).rstrip('0').rstrip('.')
这个方法。这样可以确保输出是固定小数点格式,而不是科学计数法等等。虽然这个方法没有 %g
那么简洁优雅,但它确实有效(而且我不知道怎么让 %g
永远不使用科学计数法;-)。