亲爱的堆栈交换器,
我在尝试计算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())
答案 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'>