我想打印一些浮点数,以便它们始终以十进制形式写入(例如 12345000000000000000000.0
或 0.000000000000012345
,而不是 科学记数法,但我希望结果为有一个 IEEE 754 double 的 ~15.7 有效数字,仅此而已。
我想要的是 _理想情况下_,结果是位置十进制格式的 最短 字符串,在转换为 float
时仍会产生相同的值。
众所周知,a repr
的 float
如果指数大于15,或者小于-4,则用科学记数法写成:
>>> n = 0.000000054321654321
>>> n
5.4321654321e-08 # scientific notation
如果使用 str
,结果字符串再次采用科学记数法:
>>> str(n)
'5.4321654321e-08'
有人建议我可以使用 format
和 f
标志和足够的精度来摆脱科学记数法:
>>> format(0.00000005, '.20f')
'0.00000005000000000000'
它适用于该数字,尽管它有一些额外的尾随零。但是 .1
的相同格式失败了,它给出了超出 float 实际机器精度的十进制数字:
>>> format(0.1, '.20f')
'0.10000000000000000555'
如果我的号码是 4.5678e-20
,使用 .20f
仍然会失去相对精度:
>>> format(4.5678e-20, '.20f')
'0.00000000000000000005'
因此 这些方法不符合我的要求。
这就引出了一个问题:以十进制格式打印任意浮点数的最简单且性能最好的方法是什么,其数字与 repr(n)
(或 str(n)
在 Python 中一样) 3) ,但始终使用十进制格式,而不是科学记数法。
也就是说,例如将浮点值 0.00000005
转换为字符串 '0.00000005'
的函数或操作; 0.1
到 '0.1'
; 420000000000000000.0
to '420000000000000000.0'
or 420000000000000000
and formats the float value -4.5678e-5
as '-0.000045678'
.
赏金期之后:似乎至少有 2 种可行的方法,正如 Karin 所证明的,与我在 Python 2 上的初始算法相比,使用字符串操作可以显着提高速度。
因此,
- 如果性能很重要并且需要 Python 2 兼容性;或者如果
decimal
模块由于某种原因无法使用,那么 Karin 使用字符串操作 的方法就是这样做的方法。 - 在 Python 3 上, 我稍微短一些的代码也会更快。
由于我主要是在 Python 3 上开发,我会接受我自己的答案,并将赏金奖励给 Karin。
原文由 Antti Haapala – Слава Україні 发布,翻译遵循 CC BY-SA 4.0 许可协议
不幸的是,似乎即使是带有
float.__format__
的新型格式也不支持这一点。float
repr
;并带有f
标志,默认情况下有 6 个小数位:然而,有一种方法可以得到想要的结果——不是最快的,但相对简单:
str()
或repr()
将浮点数转换为字符串Decimal
实例。Decimal.__format__
支持f
给出所需结果的标志,并且与float
不同,它打印实际精度而不是精度默认值。因此我们可以制作一个简单的效用函数
float_to_str
:必须注意不要使用全局十进制上下文,因此为此函数构造了一个新的上下文。这是最快的方法;另一种方法是使用
decimal.local_context
但它会更慢,为每次转换创建一个新的线程本地上下文和上下文管理器。此函数现在返回包含尾数中所有可能数字的字符串,四舍五入为 最短的等效表示形式:
最后的结果四舍五入到最后一位
正如@Karin 指出的那样,
float_to_str(420000000000000000.0)
与预期格式不严格匹配;它返回420000000000000000
没有尾随.0
。