【问题标题】:Prime number calculation algorithm speed makes no sense素数计算算法速度没有意义
【发布时间】:2020-12-31 10:21:38
【问题描述】:

我的问题很简单,我正在尝试计算第 n 个素数,但是在我编写的两种方法之间,我希望运行得更快的方法似乎更慢。老实说,这没有任何意义。我最初使用 python 编写了解决方案,这里是代码:

import time
import math


start1 = time.time()
primes = [2]
count = 3
primes_len = 1
while primes_len <= 10001:
    is_prime = True
    for i in range(primes_len):
        if count % primes[i] == 0:
            is_prime = False
            break
    if is_prime:
        primes_len += 1
        primes.append(count)
    count += 2
print(primes[-1])
end1 = time.time()

start2 = time.time()

listPrime = [2]
upTo = 1000000
isPrime = True

for sayi in range(3, upTo, 2):
    for bölen in range(2,int(math.sqrt(sayi)+1)):

        if (sayi % bölen) == 0:
            isPrime = False
            break

        else:
            isPrime = True

    if isPrime == True :
        listPrime.append(sayi)
        if len(listPrime) == 10001:
            break

print(listPrime[-1])

end2 = time.time()
print(end1-start1)
print(end2-start2)

尽管我希望第一个算法运行得更快(因为它只测试已知素数,因此需要更少的计算),但第二个算法的效率要高得多。认为这是一个奇怪的 python 东西导致了意外的结果,我用 C 编写了它们,这里是:

第一个:

#include <stdio.h>
#include <time.h> 
#include <stdlib.h>

int main(int argc, char **argv){
    if(argc != 2){
        printf("You must provide one argument as the nth prime to calculate");
        return 0;
    }

    clock_t begin = clock();
    long LIMIT = strtol(argv[1], NULL, 10);;
    int count = 3;
    int primes_found = 1;
    int primes[LIMIT];
    primes[0] = 2;
    int is_prime; 
    while(primes_found < LIMIT){
        is_prime = 1;
        for(int i = 0; i < primes_found; i++){
            if(count % primes[i] == 0){
                is_prime = 0;
                break;
            }
        }
        if(is_prime == 1){
            primes[primes_found] = count;
            primes_found += 1;
        }
        count += 2;
    }
    printf("%d\n", primes[LIMIT - 1]);
    clock_t end = clock();
    double time_spent = (double)(end - begin) / CLOCKS_PER_SEC;
    printf("%f\n", time_spent);
    return 0;
}

第二个:

#include <stdio.h>
#include <time.h> 
#include <stdlib.h>
#include <math.h>

int main(int argc, char **argv){
    if(argc != 2){
        printf("You must provide one argument as the nth prime to calculate");
        return 0;
    }

    clock_t begin = clock();
    long LIMIT = strtol(argv[1], NULL, 10);;
    int count = 3;
    int primes_found = 1;
    int primes[LIMIT];
    primes[0] = 2;
    int is_prime;
    while(primes_found < LIMIT){
        is_prime = 1;
        for(int i = 2; i <= (int) sqrt(count); i++){
            if(count % i == 0){
                is_prime = 0;
                break;
            }
        }
        if(is_prime == 1){
            primes[primes_found] = count;
            primes_found += 1;
        }
        count += 2;
    }
    printf("%d\n", primes[LIMIT - 1]);
    clock_t end = clock();
    double time_spent = (double)(end - begin) / CLOCKS_PER_SEC;
    printf("%f\n", time_spent);
    return 0;
}

其行为方式相同。老实说,这对我来说完全没有意义,希望对此有任何意见。

【问题讨论】:

  • 简单:第一个不会停在 sqrt(n)。

标签: python c algorithm


【解决方案1】:

考虑循环之间的区别

    for(int i = 0; i < primes_found; i++){

    for(int i = 2; i <= (int) sqrt(count); i++){

当测试素数时,让我们调用test,第一个迭代所有已知的较小素数primes[i]。当primes[i]*primes[i] &gt; test,那是浪费时间。

第二个循环迭代所有值直到sqrt(test)。这是低效的,因为许多候选除法本身不是素数。

显然,第一个的低效率是最糟糕的。


另一种方法是使用素数列表进行迭代,但在 primes[i]*primes[i] &gt; test 1 时停止。

另请参阅Sieve of Eratosthenes,了解可能更快的方法。


1 更好的是:使用primes[i] &gt; test/primes[i] 来避免溢出。

【讨论】:

    【解决方案2】:

    在你的第一个中,你忘了只求平方根。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-03-09
      相关资源
      最近更新 更多