C找出大数的素数因子

时间:2014-01-20 14:29:02

标签: c winapi long-integer

我写了下面的C代码来找出大数的最大引物因子,我的程序在运行时会一直执行。我试图通过指定范围为2 ^ 32-1的iBigNum来调试它,然后它奏效了。

LONG64 iBigNum = 600851475143,iCurr=0,iLarge=0;
    //600851475143 
    /*4294967295
      4000000000
    */iCurr = iBigNum-1;
    while(iCurr > 0 )
    {
        if(iBigNum % iCurr == 0){
            iLarge=iCurr;
            break;
        }
        iCurr--;
    }
    MsgPrintf(TEXT("CustomPrint"),TEXT("%d"),iLarge);

之间,LONG64定义为basetsd.h

//
// The following types are guaranteed to be signed and 64 bits wide.
//

typedef __int64 LONG64, *PLONG64;

我在运行3.16GHz,4 GB RAM的Intel Core 2 Duo CPU上运行代码。这是预期的行为吗?有人能给我指点方向吗? 谢谢

2 个答案:

答案 0 :(得分:3)

从顶部开始似乎是一个好主意,因为你需要找到最大的因素,但事实并非如此。最小可能因子是2,因此最大可能因子是n/2。您花费了第一次n/2,即300425737571次迭代。在你的情况下情况更糟,因为最小的因素是17。

不要试图聪明。从底部开始你的因子分解。当您找到一个因子时,将您的数字除以它,可能是几次,并存储最后一个因子。当你的号码是1时停止。

(如果你的数字是一个素数的平方,这个天真的方法仍然很糟糕,但平均来说,如果你只检查一个数字,它应该相当快。)

编辑:这是代码,它将以我上面描述的方式找到最重要的因素。它将在非素数下合理地运行,但在大型素数(479001599)上运行它在我的机器上大约需要4秒钟。 OP的原始输入量是原来的1000倍。

有了这个警告,请点击这里:

LONG64 max_fact(LONG64 iBigNum)
{
    LONG64 maxFact = 1;
    LONG64 i = 2;

    while(iBigNum > 1)
    {
        while (iBigNum % i == 0){
            iBigNum /= i;
            maxFact = i;
        }
        if (i == 2) i = 3; else i += 2;
    }

    return maxFact;
}

答案 1 :(得分:2)

你的算法非常慢。这就是它似乎永远存在的原因。

  • 你一次只减1。 2更合乎逻辑(只检查奇数除数)
  • 你从顶部做试验分工。第一个iBigNum/2你将无所事事,因为那里没有任何因素。

我建议你尝试实现一个实际的分解算法。 Pollards-Rho实现起来非常简单,并且会在几分之一毫秒内对64位整数进行分解。

#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <inttypes.h>

static inline intmax_t pollards_rho_randomiser(intmax_t x, intmax_t n) {
    return ((x * x) - 1) % n;
}

static inline intmax_t gcd(intmax_t x, intmax_t y) {
    while (y) {
        intmax_t temp = y;
        y = x % y;
        x = temp;
    }
    return x;
}

intmax_t pollards_rho(intmax_t n) {
    intmax_t x = 2, y = 2, d = 1;

    while (d == 1) {
        x = pollards_rho_randomiser(x,n);
        y = pollards_rho_randomiser(y,n);
        y = pollards_rho_randomiser(y,n);
        d = gcd(abs(x-y), n);
    }

    if (d == n)
        return 0;
    else
        return d;
}

size_t factorise(intmax_t * factors, intmax_t iBigNum) {
    size_t num_factors = 0;

    intmax_t factor;
    while ((factor = pollards_rho(iBigNum))) {
        // makes sure to split everything into primes
        num_factors += factorise(factors + num_factors, factor);
        iBigNum /= factor;
    }

    factors[num_factors++] = iBigNum;

    return num_factors;
}

int compare(const void * a, const void * b) {
    return *(intmax_t *)b - *(intmax_t *)a;
}

int main () {
    intmax_t iBigNum = 600851475143;

    intmax_t factors[200];
    size_t num_factors = factorise(factors, iBigNum);

    qsort(factors, num_factors, sizeof(*factors), compare);
    printf("%" PRIiMAX " = %" PRIiMAX, iBigNum, factors[0]);

    size_t i;
    for (i = 1; i < num_factors; i ++) {
        printf("* %" PRIiMAX, factors[i]);
    }

    printf("\n");

    return 0;
}