【问题标题】:C finding out prime factor of large numberC 找出大数的质因数
【发布时间】:2014-01-20 14:29:01
【问题描述】:

我编写了以下C代码来找出一个大数的最大引物因子,并且我的程序在运行时一直执行。我尝试通过分配iBigNum来调试它,范围为2^32-1,然后它工作。

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;

我在 Intel Core 2 Duo CPU 上运行代码,运行频率为 3.16GHz,内存为 4 GB。这是预期的行为吗?有人可以指出我的方向吗? 谢谢

【问题讨论】:

标签: c winapi long-integer


【解决方案1】:

从顶部开始似乎是个好主意,因为您需要找到最大的因素,但事实并非如此。可能的最小因子是 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;
}

【讨论】:

  • 谢谢,所以现在从 2(bottom) 开始,如果 n%2 == 0,那么最大的质因数将是 n/2,否则在其他情况下,增加数字,查找是否是因子并存储如果它大于前一个因子..直到 n/number 为 1。我应用了这个逻辑但仍然以一个长时间运行的程序结束:) 可能应该尝试实现 @Sergey L 提到的算法
  • 如果您必须进行大量分解,Sergey 的解决方案肯定是更好的解决方案。他提供了你需要的所有代码。我的解决方案的好处是易于理解和实施。我已经在我编辑的答案中提供了代码。
【解决方案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;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-04-26
    • 2016-03-17
    • 1970-01-01
    • 2023-01-13
    • 2011-08-17
    • 1970-01-01
    • 1970-01-01
    • 2013-04-11
    相关资源
    最近更新 更多