当前位置: 首页 > 面试题库 >

将float转换为位置格式的字符串(没有科学计数法和错误的精度)

敖淮晨
2023-03-14
问题内容

我想打印一些浮点数,以使它们始终以十进制形式写(例如12345000000000000000000.00.000000000000012345,而不是科学计数法,但是我希望结果具有IEEE
754倍数的最多〜15.7的有效数字,仅此而已。

理想情况下 , __float 我想要 的结果是 位置十进制格式 最短
字符串,当转换为a时仍会得到相同的值

众所周知,如果指数大于15或小于-4,则用科学记数法写repra的float

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

如果str使用,则结果字符串再次采用科学计数法:

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

有人建议我可以用formatf标志和足够的精度摆脱了科学计数法:

>>> 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上)具有相同位数的最简单且性能最佳的方法是什么,但始终使用十进制格式,而不是科学计数法。

也就是说,例如将float值转换0.00000005为string的函数或操作'0.00000005'0.1'0.1';
420000000000000000.0'420000000000000000.0'420000000000000000和格式浮点值-4.5678e-5作为'-0.000045678'

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

从而,

  • 如果性能很重要并且需要Python 2兼容性;或者,如果由于decimal某种原因而无法使用该模块,那么Karin使用字符串操作的方法就是这样做的方法。
  • 在Python 3上,我稍微短一些的代码也将更快。

由于我主要是在Python 3上进行开发,因此我将接受自己的回答,并奖励Karin。


问题答案:

不幸的是,似乎甚至没有带有float.__format__这种格式的新格式。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它,但是会比较慢,为每次转换创建一个新的线程本地上下文和一个上下文管理器。

现在,此函数返回带有尾数所有可能数字的字符串,四舍五入为最短的等效表示形式:

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



 类似资料:
  • 我想打印一些浮点数,使它们始终以十进制形式书写(例如或

  • 问题内容: 我正在尝试将一组字符串从txt文件转换为列表中的int。我能够找到一个不错的代码片段来返回每一行,然后我尝试将其转换为int。问题是数字采用科学计数法,并且出现以下错误:ValueError:int()的无效文字,基数为10:‘3.404788e-001’。 这是我一直在处理的代码 问题答案: 将或用作浮点数,具体取决于保持精度对您的重要性。 将数字存储在机器精度的IEEE浮点数中,同

  • 我需要将json字符串转换为java对象,并将其显示为long。json字符串是一个固定的长数字数组: 要转换的代码在所有情况下都可以正常工作,但以0结尾的数字除外。它将这些转换为科学符号数字格式: 实际结果:Java对象:268627104、485677888、5.068848E 8 请注意,最后一个数字已转换为科学记数法格式。有人能建议如何解决它、防止它或撤销它吗?我正在使用Gson v1.7

  • 很多问题都解决了这个问题,但没有一个解决方案能完全满足我的需要。 我有一个数据框,有两列数字,每列10-20位。这些实际上是ID,我想将它们连接起来。看起来最好先将值转换为字符串。 然而,当使用转换时,熊猫保留了科学符号,这是不会飞的。 我尝试过的事情: 尝试:dtype arg('str')或转换器(使用)在 结果:

  • 在C++中如何将浮点数转换为字符串,同时指定精度&小数位数? 例如:

  • 问题内容: 如何使用PEM格式的字符串创建实例?PEM格式的字符串是HTTP请求“ SSL_CLIENT_CERT”标头值。 答案 : 根据mgaert的回答,这是我在Scala中写的内容 : 问题答案: 将Base64解码为二进制,并用一些InputStream读取它,然后尝试