减少暴力强迫的时间复杂性 - 最大的素因子

时间:2013-08-29 19:39:15

标签: python c performance

我正在编写一个代码来查找非常大数字的最大素数因子。

  

Euler项目的问题3:    600851475143的最大主要因素是什么?

我用C语言对它进行了编码...但long long int的数据类型不足以保存该值。

现在,我已经用Python重写了代码。如何减少执行所需的时间(因为它花费了相当长的时间)?

def isprime(b):
    x=2
    while x<=b/2:
        if(b%x)==0:
            return 0
        x+=1
    return 1
def lpf(a):
    x=2
    i=2
    while i<=a/2:
        if a%i==0:
            if isprime(i)==1:
                if i>x:
                    x=i
                    print(x)
        i+=1
    print("final answer"+x)
z=600851475143
lpf(z)

4 个答案:

答案 0 :(得分:3)

有许多可能的算法加速。一些基本的可能是:

  • 首先,如果您只对最大素数因素感兴趣,则应从最大可能中检查,而不是最小值。因此,不要从2循环到a/2,而是尝试从 a downto 2检查
  • 您可以加载素数数据库,而不是使用isprime函数(网络中有数十个此类文件)
  • 此外,只有奇数可以是素数(2除外),因此您可以在每次迭代中“跳转”2个值

您的isprime检查程序也可以加速,您不必查找最高b/2的除法,只需检查sqrt(b)即可降低{{1}的复杂程度到O(n)(假设模运算是常数时间)。

答案 1 :(得分:2)

您可以使用GCC提供的128 int:http://gcc.gnu.org/onlinedocs/gcc/_005f_005fint128.html。这样,您可以继续使用C并避免必须优化Python的速度。此外,您始终可以添加自己的自定义存储类型,以便在C中保存大于长的数字。

答案 2 :(得分:1)

我认为你检查的数字太多了(递增1,每种情况下从2开始)。如果你想通过试验分区检查is_prime,你需要除以更少的数字:只开始奇数(更好的是,只有素数)。你可以通过以下方式在python中使用奇数:

for x in range(3, some_limit, 2):
    if some_number % x == 0:
      etc.

此外,一旦你有一个素数列表,你应该能够向后遍历该列表(因为该问题要求最高素数因子)并测试这些素数中的任何一个是否均匀地分成数字。

最后,人们通常会在检查试验部门时达到数字的平方根,因为超过平方根的任何东西都不会提供新的信息。考虑100:

1 x 100
2 x 50
5 x 20
10 x 10
20 x 5
etc.

只需查看数字的平方根,即可找到所有重要的除数信息。这个技巧对于测试质数和测试从哪里开始寻找那个巨大数字的潜在除数都很有用。

答案 3 :(得分:0)

首先,你的两个while循环只需要上升到sqrt(n),因为你已经击中了之前的任何东西(然后你需要检查一个/ i的完整性)。另外,如果你找到除以它的最小数字,并且除法的结果是素数,那么你找到了最大数。

首先,更正您的isprime功能:

def isprime(b):
    x=2
    sqrtb = sqrt(b)
    while x<=sqrtb:
        if(b%x)==0:
            return 0
        x+=1
    return 1

然后,你的lpf:

def lpf(a):
    x=2
    i=2
    sqrta = sqrt(a)
    while i<=sqrt(a):
        if a%i==0:
            b = a//i # integer
            if isprime(b):
                return b
            if isprime(i):
                x=i
                print(x)
        i+=1
    return x