【转摘】验证N是不是素数的算法

4 采用 Rabin-Miller 算法进行验算, Rabin-Miller 算法是典型的验证一个数字是否为素数的方法。判断素数的方法是Rabin-Miller概率测试,那么他具体的流程是什么呢。假设我们要判断n是不是素数,首先我们必须保证n 是个奇数,那么我们就可以把n 表示为 n = (2^r)*s+1,注意s 也必须是一个奇数。然后我们就要选择一个随机的整数a (1<=a<=n-1),接下来我们就是要判断 a^s=1 (mod n) 或a^((2^j)*s)= -1(mod n)(0<=j<R),如果任意一式成立,我们就说n通过了测试,但是有可能不是素数也能通过测试。所以我们通常要做多次这样的测试,以确保我们得到的是一个素数。(DDS的标准是要经过50次测试)
 
// 算法3:采用Rabin-Miller算法进行验算
// 首先选择一个代测的随机数p,计算b,b是2整除p-1的次数。然后计算m,使得n=1+(2^b)m。
 
// (1) 选择一个小于p的随机数a。
// (2) 设j=0且z=a^m mod p
// (3) 如果z=1或z=p-1,那麽p通过测试,可能使素数
// (4) 如果j>0且z=1, 那麽p不是素数
// (5) 设j=j+1。如果j<b且z<>p-1,设z=z^2 mod p,然后回到(4)。如果z=p-1,那麽p通过测试,可能为素数。
// (6) 如果j=b 且z<>p-1,不是素数
 
// 判定是否存在 a^s=1 (mod n) 或a^((2^j)*s)= -1(mod n)(0<=j<R),
 
bool Witness(int a,int n)
{
     // 解释一下数学词汇:
     // ceil 求不小于x的最小整数,函数原型extern float ceil(float x);求得i的最大值
     // log 计算x的自然对数,函数原型extern float log(float x);
     long i,d=1,x;
     for (i=(int)ceil(log((double)n-1)/log(2.0))-1;i>=0;--i)
     {
         x=d;
         d=(d*d)%n;
         if ((1==d) && (x!=1) && (x!=n-1))
         {
              return 1;
         }
         if ((n-1)&(1<0))
         {
              d=(d*a)%n;
         }
     }
     return (d!=1);
 
}
 
// 参数n,是要测定的数字,s是要内部测试的次数。
bool Rabin_Miller(int n,int s)
{
     for (int j = 0;j < s; ++j)
     {
          int a = rand()*(n-2)/RAND_MAX + 1;// 获得一个随机数1<=a<=n-1
         if (Witness(a,n))// 利用这个随即数和n进行判断对比,只要有一次返回true,就说明n不是一个素数
         {
              return false;
         }
     }
     return true;// 通过验证是一个素数
}
 
// 算法3:采用Rabin-Miller算法进行验算
// 这个算法是求大素数使用的。所以你的必须想办法支持大数字运算,
// 不然极易造成内存访问失效,我在我的机子上,MAX_NUMBER=10000时就会出现问题,1000就没有问题
void PrimeNumber3()
{
    
     int Max[MAX_NUMBER/2];// 在栈上分配,栈上空间要求一般都在2M之间,
     //   如果你需要更大空间,请在堆上申请空间(就是通过malloc,new来申请).素数的个数很少
     // 所以没有必要申请和所求数字同样大小的空间。
     int cout = 0;// 记录素数个数
     memset(Max,0,MAX_NUMBER/2);
 
     for(int i = 2; i < 1000; ++i)
     {
         if(Rabin_Miller(i,20))
         {
              Max[cout++] = i;
         }
     }
}

 

摘自: http://blog.csdn.net/ugg/archive/2006/02/16/600368.aspx 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值