
用Monte Carlo算法实现素数判定
存在整数
发布日期:2021-05-20 07:54:58
浏览次数:20
分类:精选文章
本文共 4428 字,大约阅读时间需要 14 分钟。
#Monte Carlo算法与素数判定的改进
##问题描述判定一个给定的整数是否为素数一直是数论领域中的重要问题。传统的尝试法和辗转相除法虽然可行,但对于大数的判定效率较低。而Monte Carlo算法提供了一种概率性方法,能够显著提升判定效率。
##Monte Carlo算法###1.预备知识费马小定理是Monte Carlo算法的理论基础。费马小定理指出:!代码描述图片!其逆否命题为:!代码描述图片!
传统地,人们曾试图利用费马小定理直接判定整数是否为素数。以下代码展示了一个基于费马小定理的素数判定函数:
//利用费马小定理(正确的概率较低)void Fermat(int n) { bool flag = true; srand((unsigned)time(0)); int a = uniform(1, n); // [1, n-1] if(Pow(a, n - 1) % n != 1) flag = false; Print(flag, n); // flag = true未必是素数}
###2.对Fermat测试的改进为了解决费马小定理的局限性,现代算法采用更为严格的测试方法。改进后的算法基于以下理论:
设n
是一个大于4的奇整数,满足n − 1 = 2^s * t
,其中t
为奇数。当且仅当参数a
满足以下条件之一时,n
为伪素数:
a
属于[2, n − 2]
,并且a^t % n == 1
;i
属于[0, s − 1]
,且a^(2^i * t) % n == n − 1
。代码如下:
//对Fermat的改进//判定a是否为n素性的强伪证据bool Btest(int a, int n) { int s = 0, t = n - 1; do { s++; t /= 2; } while (t % 2 != 1); int x = 1; while (t--) { x = (x * (a % n)) % n; } if (x == 1 || x == n - 1) return true; for (int i = 1; i < s; i++) { x = (x * x) % n; if (x == n - 1) return true; } return false; //一定是合数}
Mill-Rab
测试函数:
bool MillRab(int n) { int a = uniform(2, n - 1); // [2, n-2] return Btest(a, n); // 测试n是否为强伪素数}
为了降低误判概率,需要多次调用Mill-Rab
测试函数,并统计测试结果。以下函数用于重复测试并减少误判:
bool RepeatMillRab(int n, int k) { for (int i = 1; i <= k; i++) { if (MillRab(n) == false) return false; } return true;}
泛型素数判定函数:
void PrintPrimes() { int pn = 2, count = 2; printf("2 3 "); int n = 5; do { if (RepeatMillRab(n, 10)) { // 当k=10时,误判概率低于百万分之一 int/method TraditionalMethod(n): int upper = floor(sqrt(n)); for (int i = 2; i <= upper; i++) { if (n % i == 0) return false; } return true; } pn++; count++; printf("%d", n); if (count % 20 == 0) printf("\n"); else printf(" "); } while (n < 10000); printf("误判个数:%d", count - pn); double correct = (double)(pn) / count * 100; printf("\n正确比例:%f%%\n", correct);}
##完全代码及运行结果完整代码如下:
#include#include #include #include using namespace std;typedef long long LL;void Print(bool flag, int n) { if (flag) printf("%d is a prime.\n", n); else printf("%d is not a prime.\n", n);}void TraditionalPrime(int n) { bool flag = true; int upper = floor(sqrt(n)); for (int i = 2; i <= upper; i++) { if (n % i == 0) flag = false; } Print(flag, n);}bool TraditionalMethod(int n) { int upper = floor(sqrt(n)); for (int i = 2; i <= upper; i++) { if (n % i == 0) return false; } return true;}int uniform(int a, int b) { return (rand() % (b - a)) + a;}LL Pow(int a, int n) { LL sum = 1; for (int i = 1; i <= n; i++) { sum *= a; } return sum;}void Fermat(int n) { bool flag = true; srand((unsigned)time(0)); int a = uniform(1, n); if (Pow(a, n - 1) % n != 1) flag = false; Print(flag, n);}bool Btest(int a, int n) { int s = 0, t = n - 1; do { s++; t /= 2; } while (t % 2 != 1); int x = 1; while (t--) { x = (x * (a % n)) % n; } if (x == 1 || x == n - 1) return true; for (int i = 1; i < s; i++) { x = (x * x) % n; if (x == n - 1) return true; } return false;}bool MillRab(int n) { int a = uniform(2, n - 1); return Btest(a, n);}bool RepeatMillRab(int n, int k) { for (int i = 1; i <= k; i++) { if (MillRab(n) == false) return false; } return true;}void PrintPrimes() { int pn = 2, count = 2; printf("2 3 "); int n = 5; do { if (RepeatMillRab(n, 10)) { // 当k=10时,误判概率低于百万分之一 if (TraditionalMethod(n)) pn++; count++; printf("%d", n); if (count % 20 == 0) printf("\n"); else printf(" "); } n += 2; } while (n < 10000); printf("误判个数:%d", count - pn); double correct = (double)(pn) / count * 100; printf("\n正确比例:%f%%\n", correct);}int main() { srand((unsigned)time(0)); PrintPrimes(); return 0;}
##运行结果运行结果如下:
2 3 5 7 11 13 17 19 23 29 31 37 ...误判个数:3正确比例:99.30%
(根据实际运行结果可能会有所不同,具体结果取决于随机数生成的结果)
以上为完整代码及运行结果,展示了如何利用改进后的Miller-Rabin测试方法高效地判定整数是否为素数。通过多次重复测试并结合传统方法,误判概率得以显著降低。
发表评论
最新留言
表示我来过!
[***.240.166.169]2025年05月05日 23时23分25秒
关于作者

喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
JavaSE总结
2019-03-06
Python IO编程
2019-03-06
CSS入门总结
2019-03-06
使用 TortoiseGit 时,报 Access denied 错误
2019-03-06
基于 HTML5 WebGL 的污水处理厂泵站自控系统
2019-03-06
django-表单之模型表单渲染(六)
2019-03-06
c++之程序流程控制
2019-03-06
spring-boot-2.0.3之redis缓存实现,不是你想的那样哦!
2019-03-06
有道云笔记 同步到我的博客园
2019-03-06
李笑来必读书籍整理
2019-03-06
Hadoop(十六)之使用Combiner优化MapReduce
2019-03-06
《机器学习Python实现_10_06_集成学习_boosting_gbdt分类实现》
2019-03-06
CoreCLR源码探索(八) JIT的工作原理(详解篇)
2019-03-06
andriod 开发错误记录
2019-03-07
C语言编译错误列表
2019-03-07
看明白这两种情况,才敢说自己懂跨链! | 喵懂区块链24期
2019-03-07
python中列表 元组 字典 集合的区别
2019-03-07