在查看了几个类似问题的答案之后,这似乎是我的最佳解决方案:
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
3.14 == 3.140
-它们是相同的浮点数。因此,3.140000是相同的浮点数。零首先不存在。