前言:
今天搞了一天这个 蒙格马利 什么的,我自己肯定是搞不定,参照了很多资料,写一下自己的理解总结,防止忘了没地方看。
只是我个人的理解,对不对还得另说,一些公式还是不懂,只是大概的理解了下,各位当做参考吧
问题描述:
判断一个数是否是质数?
解题思路:
一开始我想的方法就是用For循环一个一个判断,后来看资料说这是最笨的方法,好吧,我得承认我数学太渣
下面开始介绍点要用到的知识:
1、积模分解公式:
具体的我就不说了,而且我也不太懂,记住这个就好:((A%C)*(B%C))%C=(A*B)%C 这个公式是用来求 蒙格马利 函数
举个例子:2^7%3 二的七次方模三 就可以换算成 ( (2^4%3)*(2^3%3))%3
2、用蒙格马利判断是否是质数:
例子:设要判断的数为num, 需要用若干个素数(也就是质数)做为参考数,假设某个素数集合为prime[] ,那么关键来了
如果 *素数集合中的每个素数数都能是这个式子成立* 即:prime[ ]^(num-1)%num==1,就可以大概说明num是个素数,反之则不是素数
素数集合一般50个素数就可以了(这只是据说,我也不知道),反正就是集合中的素数越多 ,越精确
代码:
unsigned int Montgmery(unsigned int num, unsigned index, unsigned int mod)//蒙哥马利快速幂算法 (num^index)%mod { unsigned int tmp = 1;//保存奇数是剩下的那个数 num %= mod; // 假设(2^7)%3 2%3 while (index > 1) { if (index & 1) //按位与 ,除最低位不变其他位置0 ,如果为1 说明是奇数,否则偶数 { tmp = (tmp*num) % mod;// 假设(2^7)%3 第一次为 1%3=1 (1%3)(2%3)%3=2%3 第二次 为((2%3)*(4%3))%3=8%3 } num = (num*num) % mod;//(2%3)(2%3)%3=4%3 (4%3)(4%3)%3=16%3 index /= 2; } unsigned result = (num*tmp) % mod; //(16%3)(8%3)%3=(2^7)%3 return result; }上面这个就是求 A^B%C的C语言函数,这个是优化后的版本,若是不懂继续往下看
int IsPrime(unsigned int num)//判断num是否是质数 ,如何是返回1,不是返回-1; { if (num < 2) { return -1; } static unsigned int PrimeList[] = { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31 ,37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97 };//质数表 const int count = sizeof(PrimeList) / sizeof(unsigned int);//求出置数表中数的个数 //printf("%d\n", count); int i = 0; for (i = 0; i < count; i++)//循环质数表中的每一个数 { if (num == PrimeList[i])//如果输入的数在质数表中则返回 这句绝对不能删,删了就不对了 { return 1; } //printf("%d\n", Montgmery(PrimeList[i], num - 1, num)); if (Montgmery(PrimeList[i], num - 1, num) != 1)//按照表中的质素算,如果全都为1则可以大概说num是质数 { return -1; } } return 1; }上面这个呢就是 判断是否是质数的函数,质数表没弄太多,如果想要精确的话 弄500个质数应该差不多可以达到很精确了(当然这也是据说),特别要注意的是
***** 如果你输入的数等于质数表中的某个质数的话 (prime[ ]^(num-1)%num==1)这个公式就不成立了,我也不知道为什么,我参考的资料里没说这点,所以他的那个有点小问题,我在里面加了一个判断 如果num==PrimeList[],也就是你输入的数在素数表中,就返回一,说明已经是素数了**************
void main() { static unsigned int aPrimeList[] = { // 素数表 1, 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 113, 193, 241, 257, 337, 353, 401, 433, 449, 577, 593, 641, 673, 769, 881, 929, 977, 1009, 1153, 1201, 1217, 1249, 1297, 1361, 1409, 1489, 1553, 1601, 1697, 1777, 1873, 1889, 2017, 2081, 2113, 2129, 2161, 2273, 2417, 2593, 2609, 2657, 2689, 2753, 2801, 2833, 2897, 3041, 3089, 3121, 3137, 3169, 3217, 3313, 3329, 3361, 3457, 3617, 3697, 3761, 3793, 3889, 4001, 4049, 4129, 4177, 4241, 4273, 4289, 4337, 4481, 4513, 4561, 4657, 4673, 4721, 4801, 4817, 4993, 5009, 5153, 5233, 5281, 5297, 5393, 5441, 5521, 5569, 5857, 5953, 6113, 6257, 6337, 6353, 6449, 6481, 6529, 6577, 6673, 6689, 6737, 6833, 6961, 6977, 7057, 7121, 7297, 7393, 7457, 7489, 7537, 7649, 7681, 7793, 7841, 7873, 7937, 8017, 8081, 8161, 8209, 8273, 8353, 8369, 8513, 8609, 8641, 8689, 8737, 8753, 8849, 8929, 9041, 9137, 9281, 9377, 9473, 9521, 9601, 9649, 9697, 9857 }; int count = sizeof(aPrimeList) / sizeof(unsigned int); for (int i = 0; i < count; i++) { int ret = 0; ret = IsPrime(aPrimeList[i]); if (ret == 1) { printf("是质数\n", ret); } else { printf("不是质数\n", ret); } } system("pause"); }
上面这段代码 是测试,我只测试了一堆素数,结果都对
其他的也不想说了,我是参考别人的理解的 ,并发现了别人的有点小问题,已经在前面说了,如果你看不懂,推荐你还是看看这个人的吧,我就是参考他的
http://blog.csdn.net/arvonzhang/article/details/8564836
(当然 他也是参考别人的 !!!!!!!)