Python中浮点数精度丢失

2 投票
1 回答
5047 浏览
提问于 2025-04-28 07:01

我有一个叫做 scores 的列表,里面存的是不同的负对数概率。

当我调用这个函数时:

maxState = scores.pop(scores.index(max(scores)))

然后打印 maxState,我发现 maxState 作为浮点数的时候,精度丢失了。有没有办法让我得到不失去精度的 maxState 呢?

比如,我打印出列表 scores:[-35.7971525669589, -34.67875545008369],然后打印 maxState,结果是:-34.6787554501(你可以看到它被四舍五入了)

暂无标签

1 个回答

4

你可能把字符串的显示方式和实际内容搞混了。其实并没有丢失精度,只是你在控制台看到的字符串是用一个四舍五入的值,而不是显示所有的数字。要记住,浮点数是数字的近似值,而不是精确值。

在Python中,使用 str()repr() 函数时,浮点数的格式是不同的;在列表或其他容器中会使用 repr(),但如果直接打印出来,就会用 str()

如果你对这两种方式都不满意,可以使用 format() 函数 来明确指定格式和精度:

print format(maxState, '.12f')

比如说,你想打印出8位小数。

示例:

>>> maxState = -34.67875545008369
>>> repr(maxState)
'-34.67875545008369'
>>> str(maxState)
'-34.6787554501'
>>> format(maxState, '.8f')
'-34.67875545'
>>> format(maxState, '.12f')
'-34.678755450084'

repr() 的输出大致相当于使用 '.17g' 作为格式,而 str() 则相当于 '.12g';这里的精度决定了什么时候使用科学计数法(e)和什么时候使用浮点数表示法(f)。

我说“大致”是因为 repr() 的输出旨在提供可以回溯的结果;你可以查看 Python 3.1 的浮点数表示变化说明,这些变化也被移植到了 Python 2.7:

新的变化在于数字的显示方式。以前,Python使用一种简单的方法。repr(1.1) 的值是通过 format(1.1, '.17g') 计算得出的,结果是 '1.1000000000000001'。使用17位数字的好处是,它依赖于IEEE-754标准的保证,确保 eval(repr(1.1)) 能准确返回原始值。缺点是很多人觉得这个输出让人困惑(把二进制浮点表示的固有限制误认为是Python本身的问题)。

现在 repr(1.1) 的新算法更聪明,返回的是 '1.1'。实际上,它会搜索所有等效的字符串表示(那些存储着相同底层浮点值的表示),并返回最短的表示方式。

撰写回答