版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
利用miracl库实现Fermat素性检测
Fermat素性检测是一种建立在Fermat小定理之上、针对大数的素性检测方案。它虽然能准确地判断“合数”,却无法保证“素数”结论的颠扑不破,换言之,对于“素数”的判断是概率性的。
用到的工具:VS2017、C语言大数库Miracl_5.5.4。
一、Fermat素性检测算法介绍
重要参数:待测大数m(从文件输入),安全参数k(从控制台输入)。
按如下步骤进行检验:
- 随机选取整数a,且a大于等于2,小于等于m-2。
- 计算a和m的最大公因数g。如果g不等于1(a和m不互素),判断m为合数并退出;否则转到第三步继续判断。
- 验证a和m是否满足Fermat小定理的要求。令r=am-1(mod m),若r不等于1,则违背了Fermat小定理,确定m为合数。否则m可能为素数。
- 重复k次。若最终m仍可能为素数,则其概率为1-1/(2k)。
二、miracl环境配置
参考链接:miracl库下载以及配置
前人栽树:很多同学调试时可能会遇到lib库无法正常载入的情况,有可能是文件名后缀的问题,你把cpp改为c后缀试试。
博主在这里栽了两个小时,呜呼哀哉,呜呼哀哉!!!
三、miracl基本函数
参考链接:miracl基本函数介绍
我们要用到的函数:mirsys(初始化miracl内存空间)、mirvar(big数初始化)、cinnum(大数的输入)、cotnum(大数的输出)、decr(大数与int数相减)、bigrand(生成随机big数)、egcd(计算两个大数的最大公因数)、compare(比较两个大数的大小)、powmod(计算大数之间的指数次方模值,如am-1(mod m))、mirexit(清理miracl内存空间)。
四、编程实现
#include<stdio.h>
#include<math.h>
#include<stdlib.h>
#include "miracl.h"
int main()
{
int k;
FILE *fp = NULL;
char fileName[80];
double probability = 0;
miracl *mip = mirsys(500,10); //初始化miracl系统
big m = mirvar(0);
big a = mirvar(0);
big g = mirvar(0);
big r = mirvar(0);
big temp = mirvar(0);
big one = mirvar(1);
printf("****************Fermat素性检测算法START******************\n\n");
//数据初始化:从文件中读取大数,从控制台获取安全参数k
printf("请输入待检测大数存放的文件名(含路径):");
scanf("%s", fileName);
printf("载入大数中..............\n");
if ((fp = fopen(fileName, "r+")) == NULL) {
printf("载入大数失败!\n");
system("pause");
exit(1);
}
cinnum(m, fp);
printf("载入成功!待检测的大数为:\n");
cotnum(m, stdout);
printf("\n现在请输入安全参数k:");
scanf("%d", &k);
//处理逻辑
for (int i = 1; i <= k; i++) {
printf("\n**************Fermat素性检测第%d轮****************\n", i);
//随机选取整数a
do {
decr(m, 1, temp);
bigrand(temp, a);
} while (compare(a,one)!=1);
printf("\n第%d轮生成的随机数a(2=<a=<m-2)为:\n",i);
cotnum(a, stdout);
printf("\n");
//计算g
egcd(m, a, g);
printf("第%d轮m和a的最大公因数g为:",i);
cotnum(g, stdout);
printf("\n");
if (compare(g, one)) {
printf("第%d轮检验失败:a和m不互素,故m为合数\n",i);
system("pause");
exit(0);
}
//计算r
powmod(a, temp, m, r);
printf("第%d轮用于验证Fermat小定理的r为:", i);
cotnum(r, stdout);
printf("\n");
if (compare(r, one)) {
printf("第%d次检验失败:求解出来的r不等于1,故m为合数\n",i);
system("pause");
exit(0);
}
//打印结果
probability = 1 - pow(0.5, i);
printf("第%d次检验成功:m为素数的概率为:%6.4f\n", i, probability);
}
printf("\n****************Fermat素性检测算法END******************\n");
fclose(fp);
mirexit();
system("pause");
return 0;
}
五、运行效果