为什么我的列表结构数学运算减少了几十亿?

时间:2016-08-10 19:46:06

标签: python list

我有一些非常简单的函数,它试图返回一个列表,该列表是输入列表与该列表的平均值之间的距离。代码几乎有效。有关为什么结果稍微偏离的想法?

def distances_from_average(test_list):
    average = [sum(test_list)/float(len(test_list))]*len(test_list)
    return [x-y for x,y in zip(test_list, average)]

以下是我的示例结果: [-4.200000000000003,35.8,2.799999999999997,-23.200000000000003,-11.200000000000003]应该等于[4.2,-35.8,-2.8,23.2,11.2]

2 个答案:

答案 0 :(得分:7)

这是由于计算机代表浮点数的方式。

它们并不总是以你期望的方式准确,因此不应该被用来检查平等,或代表金额等事情。

这些号码是如何使用的?如果您需要这种准确性,也许有更好的方法来使用这些信息,例如检查范围而不是检查相等性。

Here is some good reading material on the subject

答案 1 :(得分:2)

如果您没有充分考虑二进制表示浮点的方式以及可能导致的舍入错误,浮点可能会导致令人惊讶的结果。串联求和会加剧浮点舍入误差。

示例:

>>> sum([.1]*10)
0.9999999999999999   # 1.0 expected in decimal
>>> sum([.1]*1000)
99.9999999999986     # 100.0 expected
>>> sum([1, 1e100, 1, -1e100] * 10000)
0.0                  # 20000 expected

有许多方法可以获得准确的结果(使用Decimal模块,使用Fractions模块等)除了其他技术之外,可以通过在求和期间取消来消除舍入误差。您可以使用Python数学库中的fsum获得更精确的求和结果:

>>> import math
>>> math.fsum([.1]*10)
1.0
>>> math.fsum([.1]*1000)
100.0
>>> math.fsum([1, 1e100, 1, -1e100] * 10000)
20000.0

fsum功能基于Raymond Hettinger的Active State食谱。它不是完美(尝试math.fsum([1.1,2.2]*1000) ...)但它非常好。