简体   繁体   English

大量的Python优化

[英]Python optimization with big numbers

I want to print all prime numbers with 7 consecutive 7s less than 10000000000 . 我要打印所有7个连续的7s小于10000000000质数。 I was getting a MemoryError when using range() because the generated array couldn't be stored, so I changed the loop into a while loop. 使用range()时遇到了MemoryError ,因为无法存储生成的数组,因此将循环更改为while循环。

However the program is really slow. 但是该程序确实很慢。 It takes more than a minute to print the first number found. 打印发现的第一个号码需要一分钟以上的时间。

import math

def is_prime(n):
    if n % 2 == 0 and n > 2: 
        return False
    i = 3
    while i < math.sqrt(n) + 1:
    #for i in range(3, int(math.sqrt(n)) + 1, 2):
        if n % i == 0:
            return False
        i += 2
    return True

def is_super_happy(n):
    count = 0
    while n != 0:
        if n%10 == 7:
            count += 1
            if count == 7:
                return True
        else:
            count = 0
        n /= 10
    return count == 7

i = 7777777
while i < 10e10:
#for i in range(7777777, int(10e10)):
    if is_super_happy(i) and is_prime(i):
        print i
    i += 1

I can't thing of anything that could make this go faster, and I want it to be really fast. 我什么都做不了,它可以使速度更快,我希望它真的很快。

Any ideas, tips? 有什么想法,提示吗?

Your current algorithm is very wasteful: is_prime checks every number from 1 to sqrt(n) on every iteration, whereas it should only check known prime numbers. 您当前的算法非常浪费: is_prime在每次迭代中检查从1到sqrt(n)的每个数字,而它只应检查已知的质数。

Modify your algorithm so that it implements http://en.wikipedia.org/wiki/Sieve_of_Eratosthenes 修改算法,使其实现http://en.wikipedia.org/wiki/Sieve_of_Eratosthenes

In addition, you're computing sqrt(n) at every tick of your while loop (potentially several million times if you get high enough), except that it doesn't change. 另外,除了while循环不变外,您还在while循环的每个周期内计算sqrt(n) (如果您足够高的话,可能要进行数百万次计算)。 Compute it once at the beginning of the function and reuse that. 在函数开始时对其进行一次计算,然后重复使用。

Two suggestions: 两个建议:

  • Generate the 7, 8 and 9-digit numbers less than 10e10 containing 7777777 directly (rather than checking each and every number in turn) and then check them. 直接生成小于10e10包含7777777 7、8和9位数字(而不是依次检查每个数字),然后进行检查。 There are a relatively small number of such numbers. 这样的数字相对较少。

    For example, here's a way to generate a list of all such numbers which end with '7777777': [int(str(x)+'7777777') for x in xrange(100)] 例如,这是一种生成所有以'7777777' 结尾的数字的列表的方法: [int(str(x)+'7777777') for x in xrange(100)]

  • Consider using a probabilistic test for checking primality (such as Miller-Rabin ). 考虑使用概率测试来检查素数(例如Miller-Rabin )。 This tells you whether a number x is prime with a very high level of probability and is far quicker that checking potentially thousands of numbers smaller than x for divisibility. 这告诉您数字x是否是质数很高的质数,并且比检查可能小于x数以千计的数快得多。

I find 250 primes in about a quarter second, I don't want to give my code because your question looks like homework. 我在大约四分之一秒内发现了250个素数,我不想给出代码,因为您的问题看起来像是作业。

Methods: 方法:

  • first, find all the primes below 100 000 (that's sqrt(your max number)), using a sieve. 首先,使用筛子查找所有低于10万的素数(即sqrt(最大数))。
  • is_prime() only needs to check whether any of those primes divide the number is_prime()仅需要检查这些素数是否除以该数
  • There are only 4000 of these numbers; 这些数字只有4000个; consider the numbers 000 to 999. They can be combined with 7777777 in four ways; 考虑数字000到999。可以通过四种方式将它们与7777777组合; say 123 becomes 7777777123, 1777777723, 1277777773 and 1237777777. Generate those, check them against primality, done. 例如123变成7777777123、1777777723、1277777773和1237777777。生成它们,检查它们是否与素有关,完成。
  • Use strings ( int("12" + "7777777" + "3") ) or just math (12 * 100000000 + 7777777 * 10 + 3) to generate the numbers 使用字符串( int("12" + "7777777" + "3") )或仅使用数学运算(12 * 100000000 + 7777777 * 10 + 3)生成数字

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM