Python - 完美数字搜索的优化

时间:2016-11-16 10:46:01

标签: python loops optimization range perfect-numbers

p = []
for x in range(1, 50000000):
    count = 0
    for y in range(1, x // 2 + 1):
        if (x % y == 0):
            count += y
    if (count == x):
        p.append(x)

这是我的代码,可以尝试查找源自1到50000000之间的所有完美数字。它适用于前3个数字,它们介于1和10000之间。但随着它的进展,它变得极其缓慢。比如可能每10秒钟通过1000个数字。然后最终每5秒钟通过10个数字。

无论如何我现在可以加快速度吗?我尝试包括一些较小的东西,比如将x乘以2来确保我们不会超过一半(不会是x的倍数)

3 个答案:

答案 0 :(得分:2)

正如已经提到的,没有找到奇怪的完美数字。根据{{​​3}},如果存在任何奇数完美数字,则必须大于10 1500 。显然,寻找奇怪的完美数字需要复杂的方法和/或很多的时间。 :)

Wikipedia article on perfect numbers所述,欧几里德证明即使是完美的数字也可以从梅森素数中产生,而欧拉证明,相反,所有甚至完美的数字都有这种形式。

因此,我们可以通过生成Mersenne素数来生成一个甚至是完美数字的列表。我们可以(相对)快速通过Wikipedia测试一个数字是否为梅森素数。

这是一个简短的程序。这里使用的primes函数是由Robert William Hanks编写的,其余的代码几分钟前刚刚由我编写。 :)

''' Mersenne primes and perfect numbers '''

def primes(n):
    """ Return a list of primes < n """
    # From http://stackoverflow.com/a/3035188/4014959
    sieve = [True] * (n//2)
    for i in range(3, int(n**0.5) + 1, 2):
        if sieve[i//2]:
            sieve[i*i//2::i] = [False] * ((n - i*i - 1) // (2*i) + 1)
    return [2] + [2*i + 1 for i in range(1, n//2) if sieve[i]]

def lucas_lehmer(p):
    ''' The Lucas-Lehmer primality test for Mersenne primes.
        See https://en.wikipedia.org/wiki/Mersenne_prime#Searching_for_Mersenne_primes
    '''
    m = (1 << p) - 1
    s = 4
    for i in range(p - 2):
        s = (s * s - 2) % m
    return s == 0 and m or 0

#Lucas-Lehmer doesn't work on 2 because it's even, so we just print it manually :)
print('1 2\n3\n6\n')
count = 1
for p in primes(1280):
    m = lucas_lehmer(p)
    if m:
        count += 1
        n = m << (p - 1)
        print(count, p)
        print(m)
        print(n, '\n')

<强>输出

1 2
3
6

2 3
7
28 

3 5
31
496 

4 7
127
8128 

5 13
8191
33550336 

6 17
131071
8589869056 

7 19
524287
137438691328 

8 31
2147483647
2305843008139952128 

9 61
2305843009213693951
2658455991569831744654692615953842176 

10 89
618970019642690137449562111
191561942608236107294793378084303638130997321548169216 

11 107
162259276829213363391578010288127
13164036458569648337239753460458722910223472318386943117783728128 

12 127
170141183460469231731687303715884105727
14474011154664524427946373126085988481573677491474835889066354349131199152128 

13 521
6864797660130609714981900799081393217269435300143305409394463459185543183397656052122559640661454554977296311391480858037121987999716643812574028291115057151
23562723457267347065789548996709904988477547858392600710143027597506337283178622239730365539602600561360255566462503270175052892578043215543382498428777152427010394496918664028644534128033831439790236838624033171435922356643219703101720713163527487298747400647801939587165936401087419375649057918549492160555646976 

14 607
531137992816767098689588206552468627329593117727031923199444138200403559860852242739162502265229285668889329486246501015346579337652707239409519978766587351943831270835393219031728127
141053783706712069063207958086063189881486743514715667838838675999954867742652380114104193329037690251561950568709829327164087724366370087116731268159313652487450652439805877296207297446723295166658228846926807786652870188920867879451478364569313922060370695064736073572378695176473055266826253284886383715072974324463835300053138429460296575143368065570759537328128 

15 1279
10407932194664399081925240327364085538615262247266704805319112350403608059673360298012239441732324184842421613954281007791383566248323464908139906605677320762924129509389220345773183349661583550472959420547689811211693677147548478866962501384438260291732348885311160828538416585028255604666224831890918801847068222203140521026698435488732958028878050869736186900714720710555703168729087
54162526284365847412654465374391316140856490539031695784603920818387206994158534859198999921056719921919057390080263646159280013827605439746262788903057303445505827028395139475207769044924431494861729435113126280837904930462740681717960465867348720992572190569465545299629919823431031092624244463547789635441481391719816441605586788092147886677321398756661624714551726964302217554281784254817319611951659855553573937788923405146222324506715979193757372820860878214322052227584537552897476256179395176624426314480313446935085203657584798247536021172880403783048602873621259313789994900336673941503747224966984028240806042108690077670395259231894666273615212775603535764707952250173858305171028603021234896647851363949928904973292145107505979911456221519899345764984291328 

在2GHz 32位机器上,该输出在4.5秒内产生。你可以很容易地产生更大的Mersenne素数和完美的数字,但不要指望它很快。

答案 1 :(得分:1)

你可以做得更好。请考虑以下事项:

1)考虑36的因式分解,例如:1x36,2x18,3x12,4x9,6x6。就是这样。走得更远不会增加任何新东西。下一个因子分解将是9x4,但我们已经知道(4x9)。这个优势逐渐变大(比较你必须检查的最后一个数字的根与其一半)

2)没有奇怪的完美数字。这实际上是一个猜想(尚未证实),但他们尝试了低于10 ^ 300的所有内容并没有发现任何内容。所以肯定没有&lt; 50000000.这意味着您可以跳过一半的条款。

from math import ceil
p = []
for x in range(2, 50000000, 2):
    divisors = {1}
    for y in range(2, ceil(x**0.5) + 1):
        if x % y == 0:
            divisors.update({y, (x//y)})
    if sum(divisors) == x:
        print('-', x)
        p.append(x)
#- 6
#- 28
#- 496
#- 8128

这应该快得多,但肯定会有更多的事情可以做。

答案 2 :(得分:0)

以下是使用Mersenne Primes的一些预先计算值的解决方案:

mersenne_prime_powers = [2, 3, 5, 7, 13, 17, 19, 31, 61, 89, 107, 127]

def perfect_numbers(n=10):
    return [(2**p - 1) * (2**(p - 1)) for p in mersenne_prime_powers[:n]]

print(perfect_numbers(n=5))

输出:

[6, 28, 496, 8128, 33550336]