【问题标题】:python float to string without precision losspython浮动到字符串而没有精度损失
【发布时间】:2016-10-29 12:41:48
【问题描述】:

对于 python 3,我想将浮点数转换为字符串,长度可能不同(即位数),但具有完整的精度。

在任何情况下我都需要有一个小数点:

1    -> '1.'
1/10 -> '0.1000000000000000055511151231257827021181583404541015625'

目前我的代码是这样的:

from decimal import Decimal
def formatMostSignificantDigits(x):
    out = str(Decimal(x))
    if out.find('.') < 0:
        out += '.'
    return out

这可以做得更优雅吗? (e 符号也是可能的)

【问题讨论】:

  • 我的意思是,我会使用endswith 而不是.find &lt; 0,但除此之外它看起来还不错。这对于 codereview 可能会更好,因为“更优雅”并不是我们可以给你的真正客观的东西。
  • @MorganThrapp endswith 如何解决这个问题?
  • @Selcuk 哦,你是对的。抱歉,时间还早。
  • 我会使用'.' in out

标签: python python-3.x floating-point


【解决方案1】:

使用 Python string formatting functions:

>>> x = 1.0; '{:.55f}'.format(x)
'1.0000000000000000000000000000000000000000000000000000000'
>>> x = 1/10; '{:.55f}'.format(x)
'0.1000000000000000055511151231257827021181583404541015625'

如果您也希望能够为其提供整数(例如 1),请使用 '{:.55f}'.format(float(x))

如果您想去除任何尾随零,请使用'{:.55f}'.format(x).rstrip('0')

请注意,该点后的 55 位小数太过分了(但这是您在问题中显示的内容); 16 位应该足以表达双精度 IEEE 754 浮点数的完整精度(20 位表示您可能遇到的 80 位扩展精度)。

【讨论】:

  • 55 位 不是 过大,如果您想打印出浮点数的确切值。 0.1 54 位是不够的。较小的数字将需要更多的数字。最小的正 Python float 在该点之后需要超过 1000 位(准确地说是 1074)才能给出确切的值。
  • 这是我个人一直在寻找的一种解决方案,一种易于理解的单行代码
  • @MarkDickinson 双精度浮点数具有 53 位精度(大约 16 个十进制数字的值),因此如果您知道源自浮点数的数字 16 位足以表示尾数;正如0.38410446334154735661295788101073491302710874766231638 == 0.38410446334154735 =&gt; True 所证明的那样,任何更多的东西实际上都是噪音。你是对的,虽然较小的值需要更多的数字,但我没有考虑这些。这可以通过使用{:.20e} 之类的东西来解决。最终,哪个确切的解决方案是合适的取决于 OP 的确切需求。
  • 另请注意,16 个有效数字(而不是点之后的位置)通常不足以区分两个不同的 IEEE 754 binary64 浮点数:您需要 17 个数字(这就是为什么 Python 2.7 之前的版本中的 Python repr 计算 17 个有效数字并根据该计算返回输出)。
  • 您可能还想查看以下内容:stackoverflow.com/questions/48298850/…
【解决方案2】:

你为什么用Decimal,你可以用:

x = 0.1
s = str(x)
print(s)   # this prints '0.1'

但是如果你使用 Decimal 来代替这个:

out = str(Decimal(x))
if out.find('.') < 0:
    out += '.'
return out

你可以使用:

return Decimal(x).__str__()

编辑 1:

还有一个很好的浮点精度模块是 bigfloat:

from bigfloat import BigFloat
x = 0.1
print(BigFloat(x, precision(300)).__str__())
# thsi will print'0.10000000000000000555111512312578270211815834045410156250000000000000000000000000000000000000'
# but if you use this:
print(BigFloat(x.__str__(), precision(300)).__str__())
# it can be precise as much as you want
print(BigFloat(x.__str__(), precision(100000)).__str__()) # try this

【讨论】:

  • 当你投反对票时,请说出你这样做的原因。
  • 感谢您的解决方案,尤其是BigFloat 提示,谢谢
猜你喜欢
  • 2017-12-21
  • 1970-01-01
  • 2023-03-10
  • 1970-01-01
  • 1970-01-01
  • 2011-02-01
  • 2021-09-12
  • 2011-05-26
  • 1970-01-01
相关资源
最近更新 更多