【问题标题】:Python how eval a string of list with precision to decimal?Python如何评估一串精确到十进制的列表?
【发布时间】:2017-02-20 15:41:22
【问题描述】:

我有一个这样的字符串

list_str = '[148654.08425925925, 148656.99994212962, 148658.08229166668, 148661.0020601852]'

然后我使用 eval() 将其转换为 Python 中的真实列表对象

print eval(list_str)

但是,我不希望输出是四舍五入的

0 = {float} 148654.084259
1 = {float} 148656.999942
2 = {float} 148658.082292
3 = {float} 148661.00206

我怎样才能让它保持字符串中的值(精确的十进制)?

我需要使用 eval() 因为它也会使用这个列表中的其他操作

【问题讨论】:

  • 永远不要将变量命名为list等...现在您不能在该语句之后调用list(..)
  • @WillemVanOnsem 可能是 2.x,因为 print 没有括号。
  • @Ev.Kounis,猜测有什么意义?为什么“可能是 2.x”?很多人使用 Python 3。猜测这样的事情没有帮助;让 OP 回答。
  • numpy标签是否相关?
  • 只是为了指出一个明显的问题:使用 Python 3.x 而不是 Python 2.7 (可能)非常容易解决您的问题。在 Python 3.5 中,您的代码会产生您需要的结果。

标签: python python-2.7 floating-point decimal


【解决方案1】:

floats 由二进制小数表示,在与您使用的点分十进制表示 (see here) 之间进行转换时会损失精度。 python decimal package 实现了十进制浮点运算并且没有这个限制。

您不能使用eval 来分解列表,因为这些值将计算为浮点数,但您可以使用正则表达式包来提取浮点数并从那里构建列表。

>>> import decimal
>>> import re
>>> list_str = '[148654.08425925925, 148656.99994212962, 148658.08229166668, 148661.0020601852]'
>>> items = [decimal.Decimal(x) for x in re.findall(r'\d+\.?\d*', list_str)]
>>> items
[Decimal('148654.08425925925'), Decimal('148656.99994212962'), Decimal('148658.08229166668'), Decimal('148661.0020601852')]
>>> 

【讨论】:

  • 好像我没有其他想法,感谢您的有用评论。
【解决方案2】:

虽然浮点数可能会损失精度,但这里不会损失精度,因为看起来字符串是从 Python 的浮点数列表开始生成的。请注意,ast.literal_evaleval 更推荐,但是:

>>> list_str = '[148654.08425925925, 148656.99994212962, 148658.08229166668, 148661.0020601852]'
>>> import ast
>>> L = ast.literal_eval(list_str)
>>> L
[148654.08425925925, 148656.99994212962, 148658.08229166668, 148661.0020601852]

请注意,上面的内容与原始字符串完全匹配。但是,打印单个浮点数而不是整个列表默认为小数点后六位数,因此如果您想要更高的精度,请指定它:

>>> for f in L:
...     print '{:.11f}'.format(f)
...     
148654.08425925925
148656.99994212962
148658.08229166668
148661.00206018519

我还建议首先查看picklejson 模块以保存列表,以避免使用eval 甚至ast.literal_eval

【讨论】:

    【解决方案3】:

    在python中使用小数

    from decimal import *
    mlist = '[148654.08425925925, 148656.99994212962, 148658.08229166668, 148661.0020601852]'
    mlisttrim = mlist[1:-1]
    l = []
    for i in mlisttrim.split(', '):
        l.append(Decimal(i))
    print l
    

    【讨论】:

    • 我需要使用 eval() 因为它也会使用这个列表上的其他操作。
    • @BằngRikimaru,除非您非常确定需要,否则切勿使用eval()。它可以运行任意代码。你几乎从不需要它。请改用ast.literal_eval()
    • @Chris 是的,它可以改变任何东西,我有同样的想法,但我需要先用小数解决这个问题,谢谢。
    猜你喜欢
    • 1970-01-01
    • 2021-11-11
    • 1970-01-01
    • 2017-07-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-07
    • 1970-01-01
    相关资源
    最近更新 更多