【问题标题】:What's wrong with this Pollard Rho implementation这个 Pollard Rho 实现有什么问题
【发布时间】:2011-08-27 18:42:45
【问题描述】:
#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&lt;=n,但这似乎不起作用。我得到分段错误。代码有什么缺陷,如何改正?

【问题讨论】:

  • 您对while 循环的看法是正确的;没有终止,所以i 变大并使用非法值索引到x,这会导致分段错误。
  • 那么终止条件应该是什么?请查看 CLRS 中的 Pollard Rho 算法。
  • 这是一个技巧问题吗?我们怎么知道它出了什么问题?
  • 不,这不是一个技巧问题。我想知道如何更正代码。

标签: c++ algorithm factorization clrs


【解决方案1】:

我只有 CLRS 的第 1 版,但假设它与第 2 版差别不大,终止条件的答案在下一页:

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

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

【讨论】:

    【解决方案2】:

    为什么要存储所有这些中间值?你真的不需要把 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,则会加分,这样如果它无法找到一个函数的结果,它会尝试另一个函数。

    【讨论】:

    • 嗯。 whiled != 1 时终止,那么if 语句中的d != 1 不是多余的吗?
    【解决方案3】:

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-11-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-10-17
      • 2011-09-28
      • 2011-12-14
      • 2017-08-05
      相关资源
      最近更新 更多