C 找出大数的质因数
Posted
技术标签:
【中文标题】C 找出大数的质因数【英文标题】:C finding out prime factor of large number 【发布时间】: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。这是预期的行为吗?有人可以指出我的方向吗? 谢谢
【问题讨论】:
注意:"%d" 可能无法与iBigNum
一起正常工作。
@chux 谢谢,改成“%ld”
建议"%I64d"
_ _int64 或***.com/questions/3068088/…
【参考方案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;
【讨论】:
以上是关于C 找出大数的质因数的主要内容,如果未能解决你的问题,请参考以下文章
大数质因解:浅谈Miller-Rabin和Pollard-Rho算法