基于Miracl库的中国剩余定理C语言实现

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/tch3430493902/article/details/102755680

针对大数的中国剩余定理C语言实现

一、算法介绍

中国剩余定理又称孙子定理,是中国人在古代数学上的一点智慧果实(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两两互素这个条件的。

猜你喜欢

转载自blog.csdn.net/tch3430493902/article/details/102755680