这个Pollard Rho实施有什么问题

时间:2011-05-18 05:52:38

标签: c++ algorithm factorization clrs

#include <iostream>
#include <cstdlib>
typedef  unsigned long long int ULL;
ULL gcd(ULL a, ULL b)
{
   for(; b >0 ;)
   {
       ULL rem = a % b;
       a = b;
       b = rem;
   }
   return a;
}
void pollard_rho(ULL n)
{
   ULL i = 0,y,k,d;
   ULL *x = new ULL[2*n];
   x[0] = rand() % n;
   y = x[0];
   k = 2;
   while(1){
       i = i+1;
       std::cout << x[i-1];
       x[i] = (x[i-1]*x[i-1]-1)%n;
       d = gcd(abs(y - x[i]),n);
       if(d!= 1 && d!=n)
          std::cout <<d<<std::endl;
       if(i+1==k){
         y = x[i];
         k = 2*k;
       }
   }
}

int main()
{
   srand(time(NULL));
   pollard_rho(10);

}

此实施源自CLRS第2版(第894页)。 while(1)看起来很可疑。 while循环应该是什么终止条件?

我尝试了k<=n,但这似乎不起作用。我得到分段错误。代码中的缺陷是什么以及如何纠正它?

3 个答案:

答案 0 :(得分:1)

为什么存储所有这些中间值?你真的不需要把x和y放在一个数组中。只需使用您继续重复使用的2个变量,xy

另外,将while(1)替换为while(d == 1)并在

之前切断循环
 if(d!= 1 && d!=n)
      std::cout <<d<<std::endl;
   if(i+1==k){
     y = x[i];
     k = 2*k;

所以你的循环应该变成

while(d == 1)
{
    x = (x*x - 1) % n;
    y = (y*y - 1) % n;
    y = (y*y - 1) % n;
    d = abs(gcd(y-x,n))%n;
}
if(d!=n)
  std::cout <<d<<std::endl;
else
  std::cout<<"Can't find result with this function \n";

如果将循环内部使用的函数作为参数传递给pollard,那么额外的点,如果它无法通过一个函数找到结果,则会尝试另一个函数。

答案 1 :(得分:1)

我只有第一版CLRS,但假设它与第二版没有太大不同,终止条件的答案在下一页:

  

这个寻找因素的程序起初可能看起来有点神秘。但请注意,POLLARD-RHO从不打印错误答案;它打印的任何数字都是 n 的重要除数。 POLLARD-RHO可能根本不打印任何东西;无法保证会产生任何结果。但是,我们将看到有充分的理由期望POLLARD-RHO在大约sqrt之后打印 n p 因子( p while 循环的迭代。因此,如果 n 是复合的,我们可以期望这个过程在大约 n 1/4之后发现足够的除数来完全分解 n 更新,因为 n 的每个主要因子 p 除了可能的最大因素之外都小于sqrt( n )。

因此,从技术上讲,CLRS中的表示没有终止条件(这可能就是为什么他们称之为“启发式”和“程序”而不是“算法”)并且不能保证它永远不会实际上产生任何有用的在实践中,您可能希望根据预期的 n 1/4 更新来设置一些迭代。

答案 2 :(得分:0)

尝试用此替换while(1) { i = i + 1;

for (i = 1; i < 2*n; ++i) {