素数问题总结
素数问题总结
关键词 素数 判定 判断 prime 总结 问题 算法
证明:一个合数的所有因子均不大于这个数的开平方
证明:一个合数的所有因子均不大于这个数的开平方
若m不是素数则设m=x*y,其中,m>x,y>1
若x>sqrt(m),则必定y<sqrt(m)
意味着可以在[2,y]的范围内确定m是否素数。
因此只有当y=x=sqrt(m)时,y的范围才是最大值。
即素数的查找范围不大于这个数的开平方。
素数是这样的整数,它除了表示为它自己和1的乘积以外,无论他表示为任何两个整数的乘积。
筛选法思想:
是从2开始用“是则留下,不是则去掉”的方法把所有的数列出来(一直列到你不想再往下列为止,比方说,一直列到10,000)。第一个数是2,它是一个素 数,所以应当把它留下来,然后继续往下数,每隔一个数删去一个数,这样就能把所有能被2整除、因而不是素数的数都去掉。在留下的最小的数当中,排在2 后面的是3,这是第二个素数,因此应该把它留下,然后从它开始往后数,每隔两个数删去一个,这样就能把所有能被3整除的数全都去掉。下一个未去掉的数是 5,然后往后每隔4个数删去一个,以除去所有能被5整除的数。再下一个数是7,往后每隔6个数删去一个;再下一个数是11,往后每隔10个数删一个;再下 一个是13,往后每隔12个数删一个。就这样依法做下去。C语言算法
//求1000以内所有素数,用筛选法
#define SIZE 1000
int main(int argc, char *argv[])
{
int sign[SIZE];
int i, j;
for (i = 0; i < SIZE; i++){
sign[i] = 1;
}
for (i = 2; i <= sqrt(SIZE); i++){
if (sign[i]){
for (j = 2; j <= SIZE / i; j++){
sign[i*j]=0;
}
}
}
for (i = 2; i < SIZE; i++){
if(sign[i])
printf("%d,",i);
}
system("PAUSE");
return 0;
}
素数判定问题
设N=2^127-1是一个38位数,要验证它是否为素数,有下面几个不同的方法:
1.遍历2以上N的平方根以下的每一个整数,是不是能整除N;(这是最基本的方法)
1.遍历2以上N的平方根以下的每一个整数,是不是能整除N;(这是最基本的方法)
C语言描述
int isPrimeNumber(int n){
int i;
for (i = 2; i <= sqrt(n); i++){
if (n % i == 0) return 0;
}
return 1;
}
2.遍历2以上N的平方根以下的每一个素数,是不是能整除N;(这个方法是上面方法的改进,但要求N平方根以下的素数已全部知道)
但以上算法都不适合长整数的素数判断,通常会采用概率算法。
素数判定概率算法
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如果任意一式成立,我们就说n通过了测试,但是有可能不是素数也能通过测试。所以我们通常要做多次这样的测试,以确保我们得到的是一 个素数。(DDS的标准是要经过50次测试)采用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且z<>p-1,设z=z^2 mod p,然后回到(4)。如果z=p-1,那麽p通过测试,可能为素数。
(6) 如果j=b 且z<>p-1,不是素数