python sum(dict.values())给出错误的结果?

时间:2014-04-24 02:38:50

标签: python python-2.7 dictionary sum

亲爱的堆栈交换器,

我在尝试计算python字典中的值总和时遇到了一个奇怪的结果。如果我的字典超过了一定的大小,则以下函数:sum(dict.values())似乎会给出错误的结果。似乎结果在没有明显原因的情况下突然变为负面。我在Windows 7上使用python 2.7。(我为我的编码风格提前道歉)。

请注意我在处理https://projecteuler.net/problem=72时遇到了这种情况,但我并没有寻求帮助来获得答案,我只是对内置函数的行为感到困惑。 (我也为在公共论坛上发布部分解决方案而道歉,如果您不想要任何提示,请立即离开。)

程序的目标在项目Euler链接(上图)中解释,但我将尝试简要解释我的代码:

第一个函数使用Sieve of Erasthenes生成素数列表和修改过的筛子,以生成指定范围内的{composite_number:[prime_factor_list]}字典。

第二个函数试图计算可以产生的形式n / d的分数的数量,其中n

最初我使用了一个简单的计数器(初始化计数为0然后根据需要增加),但决定尝试使用字典。令我惊讶的是,这两种方法给出了不同的结果,但只有当上限(d)超过一定的大小时。我进行了更深入的探索,并设法隔离了计数分歧的确切时刻。底部附近的行if 88000 < i < 88055:标识dict值之和开始与简单计数不同的点。对于最大i = 88032的值,该值相同,但是当i = 88033时,值显着偏离:

from collections import defaultdict

def primeset(limit):
    pr = [0]*(limit+1)
    for i in range(2,limit+1):
        j = i
        i += j
        while i <= limit:
            pr[i] = 1
            i += j
    primes = [k for k in range(2,limit+1) if pr[k] == 0]
    composites = defaultdict(list)
    for p in primes:
        q = p
        p += q
        while p <= limit:
            composites[p].append(q)
            p += q
    return primes, composites


def method2(limit):
    primes, composites = primeset(limit)
    prf = {}
    count = 0
    count += limit-1
    count += (limit-2)/2
    prf[1] = limit-1
    prf[2] = (limit-2)/2    
    for i in primes:
        if i != 2:
            tally = limit-i-(limit/i)+1
            count += tally
            prf[i] = tally
    for i in composites:
        tally = limit-i
        for item in composites[i]:
            tally -= (limit/item-i/item)
        count += tally
        prf[i] = tally
        if 88000 < i < 88055:
            print i, count, tally, sum(prf.values())
    return count, prf

result, index = method2(88547)

print result,sum(index.values())

我希望我做过一些非常愚蠢的事情,但我觉得有必要把它放在那里以防万一有些不妥。

此致

1 个答案:

答案 0 :(得分:3)

你遇到整数溢出的问题,在Python中不应该发生。你有一个32位的机器,所以最大的正常整数是(2 ^ 31 - 1)。一旦你的计算超过了Python,就应该自动切换到使用长度来进行计算,这个长度不受它可以支持的数量的限制。我只有64位机器,但同样的事情适用,除了最大整数是(2 ^ 63 - 1)。你可以从shell中判断你有多长时间,因为在数字之后打印了L.这是我的shell中的一个例子:

>>> 2**62 - 1 + 2**62  # This is max int
9223372036854775807
>>> 2**63  # This is a long
9223372036854775808L
>>> num = 2**62 - 1 + 2**62
>>> num
9223372036854775807
>>> num+1
9223372036854775808L
>>> d = {1:2**62,2:-1,3:2**62}
>>> sum(d.values())
9223372036854775807
>>> d = {1:2**62,2:-1,3:2**62,4:1}
>>> sum(d.values())
9223372036854775808L

就我的情况而言,在64位计算机上的Linux上使用Python 2.7,这一切都按预期工作。

现在我使用Spyder运行相同的东西,我得到了错误的答案:

>>> d = {1:2**62,2:-1,3:2**62,4:1}
>>> sum(d.values())
-9223372036854775808

当我只是正常添加时,它正确地促进,但是来自字典的这个总和给出了错误的答案。这不是字典特有的,只是和函数。列表同样如此:

>>> list = [2**62, -1, 2**62, 1]
>>> sum(list)
-9223372036854775808

因此问题与Spyder中的sum()函数隔离,并且发生在32位和64位计算机上。

真正的答案是Spyder自动导入numpy。 Numpy有自己的sum函数版本。它描述如下&#34;算术在使用整数类型时是模块化的,并且在溢出时不会产生错误。&#34;您正在使用该版本的总和,这是导致问题。如果您不想使用该金额,可以将以下内容放在文件的顶部:

from __builtin__ import sum

这将导致使用内置版本的sum,您将得到正确的答案。

要弄清楚总和不是来自我认为来自的地方我可以使用以下内容:

>>> import inspect
>>> inspect.getmodule(sum)
<module 'numpy.core.fromnumeric' from '/usr/lib/python2.7/dist-packages/nump/core/fromnumeric.pyc'>