C++ 如何加速这个素性测试

C++ 如何加速这个素性测试,c++,primes,C++,Primes,我想找出给定数的最大素因子。经过几次尝试,我已经增强了测试,以应对相当大的数字(即10亿毫秒)。现在的问题是,如果超过10亿,那么执行时间可以说是永远的。我想知道我是否可以做更多的改进,减少执行时间。我希望有更好的执行时间,因为在这个链接中,执行时间非常快。我现在的目标号码是600851475143。代码是相当不言自明的注意:我考虑过Eratosthenes算法的筛选,但在执行时间方面没有运气 #include <iostream> #include <cmath> b

我想找出给定数的最大素因子。经过几次尝试,我已经增强了测试,以应对相当大的数字(即10亿毫秒)。现在的问题是,如果超过10亿,那么执行时间可以说是永远的。我想知道我是否可以做更多的改进,减少执行时间。我希望有更好的执行时间,因为在这个链接中,执行时间非常快。我现在的目标号码是600851475143。代码是相当不言自明的注意:我考虑过Eratosthenes算法的筛选,但在执行时间方面没有运气

#include <iostream>
#include <cmath>

bool isPrime(int n)
{
    if (n==2)
        return true;

    if (n%2==0)
        return false;

    for (int i(3);i<=sqrt(n);i+=2) // ignore even numbers and go up to sqrt(n)
        if (n%i==0)
            return false;

    return true;
}

int main()
{
    int max(0);
    long long target(600851475143);

    if( target%2 == 0 )
        max = 2;

    for ( int i(3); i<target; i+=2 ){ // loop through odd numbers. 
        if( target%i == 0 )  // check for common factor
            if( isPrime(i) ) // check for prime common factor
                max = i;
    }

    std::cout << "The greatest prime common factor is " << max << "\n";


    return 0;
}
#包括
#包括
bool isPrime(int n)
{
如果(n==2)
返回true;
如果(n%2==0)
返回false;

对于(inti(3);i我可以看到的一个明显的优化是:

for (int i(3);i<=sqrt(n);i+=2) // ignore even numbers and go up to sqrt(n)
我认为这可能导致加速的原因是
sqrt
处理
浮点算术运算
,而编译器通常在优化浮点算术运算方面并不慷慨。gcc有一个特殊的标志来明确地启用浮点优化

对于达到您提到的目标范围的数字,您需要更好的算法。应该足够了

下面是代码(),它几乎不需要花费任何时间来完成:

int main() {
    long long input = 600851475143;
    long long mx = 0;
    for (int x = 2; x <= input/x; ++x){
        while(input%x==0) {input/=x; mx = x; }

    }
    if (input > 1){
        mx = input;
    }
    cout << mx << endl;
    return 0;
}
intmain(){
长-长输入=600851475143;
长mx=0;
对于(int x=2;x 1){
mx=输入;
}

请注意,除了2和3之外,所有素数都与6的倍数相邻

以下代码将总迭代次数减少了:

  • 利用上述事实
  • 每次发现新的素因子时,减少
    target

#包括
布尔检查因子(长-长和目标,长-长因子)
{
如果(目标%系数==0)
{
do目标/=因子;
而(目标百分比系数==0);
返回true;
}
返回false;
}
长GetMaxFactor(长目标)
{
长最大因子=1;
if(检查系数(目标,2))
maxFactor=2;
if(检查系数(目标,3))
最大因子=3;
//仅检查与6的倍数相邻的系数
对于(长-长系数=5,相加=2;系数*系数1)
回报目标;
返回最大因子;
}
int main()
{
长目标=600851475143;

std::cout
for(inti(3);i您不需要素性测试。请尝试以下算法:

function factors(n)
    f := 2
    while f * f <= n
        if n % f == 0
            output f
            n := n / f
        else
            f := f + 1
    output n
功能因子(n)
f:=2

而f*f这是我的基本版本:

int main() {
    long long input = 600851475143L;

    long long pMax = 0;

    // Deal with prime 2.
    while (input % 2 == 0) {
        input /= 2;
        pMax = 2;
    }

    // Deal with odd primes.
    for (long long x = 3; x * x <= input; x += 2) {
        while (input % x == 0) { 
            input /= x;
            pMax = x;
        }
    }

    // Check for unfactorised input - must be prime.
    if (input > 1) {
        pMax = input;
    }

    std::cout << "The greatest prime common factor is " << pMax << "\n";

    return 0;
}
intmain(){
长输入=600851475143L;
长pMax=0;
//处理质数2。
while(输入%2==0){
输入/=2;
pMax=2;
}
//处理奇数素数。
用于(长x=3;x*x1){
pMax=输入;
}

std::我们可以尝试使用更高级的算法,比如。旁白:
sqrt
是一个浮点函数;您依赖它返回准确的结果,但它不能保证返回准确的结果。@Hurkyl而且在任何情况下,他都应该测试
i*i@Alnitak
i,顺便说一句:)显然,最大的优化是通过确保原始数字除以找到的每个因子来实现的。这在这里解释得很糟糕。此外,您真正想要的
x*x应该是
auto maxFactor=static_cast(sqrt(n))
;这样,每次比较都不会将
i
提升为
float
。还有一种非常快速的方法,可以不使用浮点而获得平方根的整数部分。@Spencer根本不需要执行任何平方根操作。如果单独处理2,则可以将循环所花费的时间减半,而不必使用浮点运算。@Spencer然后从
x=3
开始循环,并增加2。对于这个特定的数字,
i
的大小无关紧要,因为它将获得的最大值将适合
短的
。鉴于你似乎知道基本测试,我很惊讶你没有完全消除
sqrt
调用。@Alnitak:
600851475143
适合于
short
??为什么我要取消对函数
sqrt
的调用?除数适合于short,而不是被分解的数字。你应该取消对sqrt的调用,因为与
I*I
n
@Alnitak相比,它的成本非常高。这是一个函数调用
O(n)
乘法。你怎么能如此确定后者总是更有效?@Alnitak:无论如何……我已经完全改变了我的答案。因为,OP正在为完全相同的(最终)执行两个相同“量级”的独立循环出于这个目的,我决定不尝试改进他/她的解决方案,而是提出一个新的解决方案。
for ( int i(3); i<target; i+=2 ){ // loop through odd numbers. 
    if( target%i == 0 )  // check for common factor
        if( isPrime(i) ) // check for prime common factor
            max = i;
function factors(n)
    f := 2
    while f * f <= n
        if n % f == 0
            output f
            n := n / f
        else
            f := f + 1
    output n
int main() {
    long long input = 600851475143L;

    long long pMax = 0;

    // Deal with prime 2.
    while (input % 2 == 0) {
        input /= 2;
        pMax = 2;
    }

    // Deal with odd primes.
    for (long long x = 3; x * x <= input; x += 2) {
        while (input % x == 0) { 
            input /= x;
            pMax = x;
        }
    }

    // Check for unfactorised input - must be prime.
    if (input > 1) {
        pMax = input;
    }

    std::cout << "The greatest prime common factor is " << pMax << "\n";

    return 0;
}
    long long limit = iSqrt(input)
    for (long long x = 3; x <= limit; x += 2) {
        if (input % x == 0) {
            pMax = x;
            do {
                input /= x;
            } while (input % x == 0);
            limit = iSqrt(input); // Value of input changed so reset limit.
        }
    }