我想打印一些浮点数,以便它们总是以十进制形式写入(例如12345000000000000000000.00.000000000000012345,不是scientific notation,但我希望结果是IEEE 754的高达15.7 significant figures倍,而不是更多).

我想要的是ideally so that the result is the shortest string in positional decimal format that still results in the same value when converted to a 100.

众所周知,如果指数大于15或小于-4,则float中的repr用科学记数法表示:

>>> n = 0.000000054321654321
>>> n
5.4321654321e-08  # scientific notation

如果使用了str,则生成的字符串也是科学记数法:

>>> str(n)
'5.4321654321e-08'

有人建议,我可以使用formatf标志,并有足够的精度来摆脱科学符号:

>>> format(0.00000005, '.20f')
'0.00000005000000000000'

它适用于这个数字,尽管它有一些额外的尾随零.但同样的格式在.1中失败,这使得十进制数字超出了浮点的实际机器精度:

>>> format(0.1, '.20f')
'0.10000000000000000555'

如果我的数字是4.5678e-20,使用.20f仍然会失go 相对精度:

>>> format(4.5678e-20, '.20f')
'0.00000000000000000005'

因此these approaches do not match my requirements.


这就引出了一个问题:以十进制格式打印任意浮点数,与repr(n) (or str(n) on Python 3)中的数字相同,但始终使用十进制格式,而不是科学记数法,最简单也是性能最好的方法是什么.

即,例如将浮点值0.00000005转换为字符串'0.00000005'的函数或操作;0.1'0.1'420000000000000000.0'420000000000000000.0'420000000000000000,并将浮点值-4.5678e-5格式化为'-0.000045678'.


在赏金期之后:似乎至少有两种可行的方法,正如Karin证明的那样,与我在Python 2上的初始算法相比,使用字符串操作可以显著提高速度.

因此

由于我主要是在Python 3上开发,我将接受自己的答案,并将奖励卡林.

推荐答案

不幸的是,它似乎不支持这种格式.floats的默认格式与repr相同;对于f标志,默认情况下有6个小数位数:

>>> format(0.0000000005, 'f')
'0.000000'

然而,有一种方法可以达到预期的效果——不是最快的,而是相对简单的:

  • 首先,使用str()repr()将浮点转换为字符串
  • 然后根据该字符串创建一个新的Decimal实例.
  • Decimal.__format__支持给出所需结果的f标志,与floats不同,它打印的是实际精度而不是默认精度.

因此,我们可以制作一个简单的实用函数float_to_str:

import decimal

# create a new context for this task
ctx = decimal.Context()

# 20 digits should be enough for everyone :D
ctx.prec = 20

def float_to_str(f):
    """
    Convert the given float to a string,
    without resorting to scientific notation
    """
    d1 = ctx.create_decimal(repr(f))
    return format(d1, 'f')

必须注意不要使用全局十进制上下文,因此将为此函数构造一个新上下文.这是最快的方法;另一种方法是使用decimal.local_context,但速度较慢,为每次转换创建一个新的线程本地上下文和上下文管理器.

该函数现在返回尾数中所有可能数字的字符串,四舍五入到shortest equivalent representation:

>>> float_to_str(0.1)
'0.1'
>>> float_to_str(0.00000005)
'0.00000005'
>>> float_to_str(420000000000000000.0)
'420000000000000000'
>>> float_to_str(0.000000000123123123123123123123)
'0.00000000012312312312312313'

最后一个结果在最后一位四舍五入

正如@Karin所指出的,float_to_str(420000000000000000.0)并不完全符合预期的格式;它返回420000000000000000,不带尾随.0.

Python-3.x相关问答推荐

是否有必要使用Threads()中的args显式地将共享变量传递给Python中的线程函数或直接访问它?

为什么我在BLE中的广告代码在发送包裹之间需要大约1秒

在 python 中使用正则表达式在行尾查找特定元素

如何在 histplot 中标记核密度估计

如何转置和 Pandas DataFrame 并命名新列?

Einsum 对于张量乘法很慢

通过最接近的匹配合并两个不同长度的列上的两个数据框

为什么 setattr 在绑定方法上失败

命名元组内命名元组的 Python 语法

两个字符串之间的正则表达式匹配?

Python:如何在三个列表中找到共同值

为什么Pandas会在 NaN 上合并?

str.format_map(mapping) 和 str.format 有什么区别

Python 3:函数参数中的省略号?

Jupyter Notebook - 在函数内绘图 - 未绘制图形

在python中,如果一个函数没有return语句,它会返回什么?

try 在 Mac OS 中运行此命令pipenv install requests时出错

连接 dict 值,它们是列表

无法解码 Python Web 请求

字典理解中的操作顺序