版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
一、算法介绍
中国剩余定理又称孙子定理,是中国人在古代数学上的一点智慧果实(finally),总算是在世界数学史上找到了一个位置吧。
下面就把算法的具体过程贴出来:
关于中国剩余定理的内容介绍:
可以看到中国剩余定理就是用来求同余方程组的,前提条件是k个方程的模底数mj两两互素,然后在满足条件的情况下求M序列和M逆序列,最后求出模m的方程组解x。
关于算法步骤:
很清晰!!!
二、代码实现
话说在前头:这里只是针对三个同余方程组,aj和mj存放在一个文件里以换行符隔开,且每一个大数的位数是有限制的。如果你想计算多个同余方程组的话设置一个计数变量k就行了。
#include<stdio.h>
#include<math.h>
#include<stdlib.h>
#include"miracl.h"
int main()
{
int j = 0;
char fileName[100];//存放aj和mj的文件名
FILE *fd = NULL;
miracl *mip = mirsys(5000, 10);
big aj[3], mj[3], Mj[3], Mj_inverse[3], m, x, temp, one;
//大数初始化
m = mirvar(1);
one = mirvar(1);
x = mirvar(0);
temp = mirvar(0);
for (j = 0; j < 3; j++) {
aj[j] = mirvar(0);
mj[j] = mirvar(0);
Mj[j] = mirvar(0);
Mj_inverse[j] = mirvar(0);
}
printf("****************中国剩余定理_START*******************\n");
printf("请输入含aj和mj的文件名:");
scanf("%s", fileName);
//打开文件,并赋值aj和mj数组
if ((fd = fopen(fileName, "r+")) == NULL) {
printf("含aj和mj序列文件打开失败!\n");
system("pause");
return 1;
}
printf("你输入的aj序列为:\n");
for (j = 0; j < 3; j++) {
cinnum(aj[j], fd);
cotnum(aj[j], stdout);
printf("\n");
}
printf("你输入的mj序列为:\n");
for (j = 0; j < 3; j++) {
cinnum(mj[j], fd);
cotnum(mj[j], stdout);
printf("\n");
}
printf("\n输入结束,进入处理逻辑\n");
//处理区_start
//1.判断大数mj是否两两互素
for (j = 0; j < 3; j++)
for (int i = j + 1; i < 3; i++) {
egcd(mj[j], mj[i], temp);
if (compare(temp, one)) {
printf("oops!看来有两个mj并不互素,程序结束\n");
system("pause");
return 1;
}
}
printf("\n正整数mj两两互素? 判断成功!\n");
//2.计算m
for (j = 0; j < 3; j++)
multiply(m, mj[j], m);
printf("\nm的值为:\n");
cotnum(m, stdout);
//3.计算所有的Mj
for (j = 0; j < 3; j++) {
copy(m, temp);
divide(temp, mj[j], Mj[j]);
}
printf("\n计算出Mj序列的值为:\n");
for (j = 0; j < 3; j++) {
cotnum(Mj[j], stdout);
printf("\n");
}
printf("\n");
//4.计算所有的Mj_inverse
for (j = 0; j < 3; j++)
xgcd(Mj[j], mj[j], Mj_inverse[j], Mj_inverse[j], Mj_inverse[j]);
printf("\n计算出Mj_inverse(mod mj)序列的值为:\n");
for (j = 0; j < 3; j++) {
cotnum(Mj_inverse[j], stdout);
printf("\n");
}
printf("\n");
//5.计算最终的结果x(mod m)
//这里要说明的是,以下有些大数被重写了,只是为了填充函数参数而已。
for (j = 0; j < 3; j++) {
multiply(Mj[j], Mj_inverse[j], Mj[j]);
multiply(Mj[j], aj[j], temp);
divide(temp, m, Mj_inverse[j]);
add(x, temp, x);
}
divide(x, m, temp);
printf("\n最终的结果x为:\n");
cotnum(x, stdout);
//处理区_end
fclose(fd);
mirexit(0);
printf("\n****************中国剩余定理_END*********************\n");
system("pause");
return 0;
}
三、结果截图
我这里的测试数据是不符合m两两互素这个条件的。