优化了第 n 个质数执行时间的 c++ 函数

Optimized c++ function for nth prime number execution time

本文关键字:执行时间 c++ 函数 优化      更新时间:2023-10-16

我正在实现一个 c++ 函数,使用一些预定义的索引来获取第 N 个素数,以实现时间优化目的。

我的代码是:

// file prime.cpp
#include <iostream>
#include <time.h>
using namespace std;
/*
#define primeAt10000 104743
#define primeAt20000 224743
#define primeAt30000 350381
#define primeAt40000 479951
#define primeAt50000 611977
*/
int prime(int n){
    int pos = 1,i = 1,temp;
    if(n==0)
        return 2;
    /*
    else if(n>50000){
        i = primeAt50000;
        pos = 50001;
    }else if(n>40000){
        i = primeAt40000;
        pos = 40001;
    }else if(n>30000){
        i = primeAt30000;
        pos = 30001;
    }else if(n>20000){
        i = primeAt20000;
        pos = 20001;
    }else if(n>10000){
        i = primeAt10000;
        pos = 10001;
    }*/
    while( i+=2 ){
        temp = i/2+1;
        for(int j = 3 ; j <= temp ; j+=2)
            if(i%j == 0)
                goto con;
        if(pos++ >= n)
            return i;
        con :;
    }
}
int main(int argc, char const *argv[]){
    int index;
    cin >> index;
    clock_t start = clock();
    cout << prime(index)<<endl;
    cout << (clock()-start)/CLOCKS_PER_SEC<<"sec"<< endl; 
    return 0;
}

编译方式:

g++ prime.cpp -o prime.exe

我为输入 9999、19999 和 29999 运行了三次此代码

第一轮:1秒6秒14秒

第二轮:1秒7秒15秒

第3轮:1秒7秒16秒

再次启用注释代码后,我使用相同的输入运行了三次

第一次运行:1

秒5秒8秒

第二轮:1

秒5秒8秒

第3轮:1

秒5秒8秒

我的问题是:

为什么第二次编译后每次执行的时间差异如此之大,而循环每次运行 ~1,25,000 次?

为什么对于输入 19999(~104743 循环时间(它比第一次编译后的前 3 次运行(~224743 循环时间(更接近?

每个 9999 间隔的时间差异是不同的,因为当我们转向较大的数字来检查它是素数还是不素数时,它比较小的数字花费更多的时间。

换句话说,我们可以直接说 prime(( 中 for 循环的运行时间增加了,因为变量 temp 的值更大。

当我们检查 i = 101 时,temp 的值变为 51,for-loop 将运行大约 25 次。

而当我们检查 i = 10001 时,temp 的值变为 5001,for-loop 将运行大约 2500 次。

For 循环的这种运行时间差异将增加整体时间复杂度。

经过与@JonathanLeffler的讨论,我进一步优化了这个函数,以实现更大的输入值的最快输出,如索引 9999、19689 等......

现在我的素数函数的复杂度是 (N^2(/12,不像以前是 (N^2(/8]。

我的新代码是:

#include <iostream>
#include <time.h>
using namespace std;
#define primeAt10000 104743-7
#define primeAt20000 224743-7
#define primeAt30000 350381-7
#define primeAt40000 479951-7
#define primeAt50000 611977-7
bool checkPrime(int x){
    int temp = x/2+1;
    for(int j = 3 ; j <= temp ; j+=2)
        if(x%j == 0)
            return false;
    return true;
}
int prime(int n){
    int pos = 2,i = 0;
    if(n==0)
        return 2;
    else if(n==1)
        return 3;
    else if(n>50000){
        i = primeAt50000;
        pos = 50000;
    }else if(n>40000){
        i = primeAt40000;
        pos = 40000;
    }else if(n>30000){
        i = primeAt30000;
        pos = 30000;
    }else if(n>20000){
        i = primeAt20000;
        pos = 20000;
    }else if(n>10000){
        i = primeAt10000;
        pos = 10000;
    }
    while( i+=6 ){
        if(checkPrime(i-1))
            if(pos++>=n)
                return i-1;
        if(checkPrime(i+1))
            if(pos++>=n)
                return i+1;
    }
    return 0;
}
int main()
{
    int index;
    cin >> index;
    clock_t start = clock();
    cout << prime(index)<<endl;
    cout << (clock()-start)/(float)CLOCKS_PER_SEC<<"sec";
    return 0;
}

编译者(作为@NathanOliver&@JonathanLeffler的建议(:

g++ -O3 -Wall -Werror -Wextra prime.cpp -o prime.exe

现在是素数.exe分别采用 1.34、4.83 和 7.20 秒来输入 9999、19999 和 29999。