中国剩余定理miracl大数库实现

中国剩余定理2020

又到了熟悉的环节,把代码贴出来自己有时间修改,最终的代码将会在验收后进行公开。

在这里插入图片描述

/*
creator:bur@n
date:2020-10-20
*/

extern "C" {
#include "miracl.h"
}

#include <stdio.h>
#include <stdlib.h>
//设置组数的数量是GROUP
#define GROUP_NUM 3
#define ARRAY_SIZE 500

//声明结构体
struct each_group_info {
	char a[ARRAY_SIZE];
	char m[ARRAY_SIZE];
}Each_group_info[GROUP_NUM];


//一些供主函数调用的函数
//欢迎界面
void print_welcome();
//手动输入
void input_by_hand();
//读文件函数
int read_file(char str[]);
//核心函数
int chinese_last_fun(struct each_group_info Each_group_info[]);

//欢迎界面
void print_welcome() {
	printf("---------------------------------------------------\n");
	printf("欢迎使用中国剩余定理计算\n");
	printf("---------------------------------------------------\n\n");
	printf("请选择您要使用的功能\n 1手动输入		2读取文件		3退出\n");

}

//手动输入
void input_by_hand() {
	int i, flag = 0;
	//声明了这个类型数组
		for (i = 0; i < GROUP_NUM; i++) {
		printf("输入Each_group_info[%d].a\n", i);
		scanf("%s", Each_group_info[i].a);
		//遇到空格就把信息存入到m中
		printf("输入Each_group_info[%d].m\n", i);
		scanf("%s", Each_group_info[i].m);
		printf("\n");
	}
		//将输入文件信息列出来
		printf("\n文件信息如下:\n");
		for (i = 0; i < GROUP_NUM; i++) {
			printf("%s,%s\n", Each_group_info[i].a, Each_group_info[i].m);
		}
		printf("\n");


	//开始调用核心函数
	flag = chinese_last_fun(Each_group_info);


}

//读文件函数
int read_file(char str[]) {
	FILE *fp;
	int i, flag = 0;
	if ((fp = fopen(str, "r+")) == NULL) {
		printf("打开文件%s失败", str);
		return 0;
	}
	else {
		//printf("打开文件%s成功!\n", str);
		//打开文件成功后进行后续操作
		for (i = 0; i < GROUP_NUM; i++) {
			fscanf(fp, "%s %s", Each_group_info[i].a, Each_group_info[i].m);
		}
		fclose(fp);
		//将读取的文件数据列出来
		printf("\n文件信息如下:\n");
		for (i = 0; i < GROUP_NUM; i++) {
			printf("%s,%s\n", Each_group_info[i].a, Each_group_info[i].m);
		}
		printf("\n");

		//开始调用核心函数
		flag = chinese_last_fun(Each_group_info);
		return 0;
	}
}

//核心函数
int chinese_last_fun(struct each_group_info Each_group_info[GROUP_NUM]) {
	//传进来的是一个结构体数组,我们需要对数组进行操作
	int i, j;
	char str[ARRAY_SIZE],str1[ARRAY_SIZE];
	//我们需要设置一些大数变量
	big a[GROUP_NUM], m[GROUP_NUM], Xj[GROUP_NUM], Mj[GROUP_NUM], Mj_1[GROUP_NUM];
	big one, temp, temp1, m_factor, m_mult, m_mult_temp;

	miracl *mip = mirsys(ARRAY_SIZE, 10);
	mip->IOBASE = 10;
	one = mirvar(1);
	m_mult = mirvar(1);
	m_mult_temp = mirvar(1);
	temp = mirvar(1);
	temp1 = mirvar(0);
	m_factor = mirvar(1);


	//初始化变量
	for (i = 0; i < GROUP_NUM; i++) {
		a[i] = mirvar(0);
		m[i] = mirvar(0);
		Xj[i] = mirvar(0);
		Mj[i] = mirvar(0);
		Mj_1[i] = mirvar(0);
	}


	//将字符型变量转换成大数
	for (i = 0; i < GROUP_NUM; i++) {
		cinstr(a[i], Each_group_info[i].a);
		cinstr(m[i], Each_group_info[i].m);
		//cotnum(a[i], stdout);
		//cotnum(m[i], stdout);
	}

	//判断是否两两互素
	for (i = 0; i < GROUP_NUM; i++) {
		for (j = i + 1; j < GROUP_NUM; j++) {
			//判断m[i]和m[j]的最大公因数
			egcd(m[j], m[i], m_factor);
			if (compare(m_factor, one) != 0) {
				printf("不能直接利用中国剩余定理\n");
				return 0;
			}
		}
	}


	//计算所有m的乘积值
	for (i = 0; i < GROUP_NUM; i++) {
		multiply(m[i], m_mult, m_mult);
	}


	copy(m_mult, m_mult_temp);
	//打印输出m的值
	printf("计算得到的m是:");
	cotnum(m_mult, stdout);
	printf("\n");
	//计算所有的Mj_1和Mj
	for (i = 0; i < GROUP_NUM; i++) {
		divide(m_mult, m[i], Mj[i]);
		cotstr(m[i], str1);
		//xgcd函数需要仔细使用
		xgcd(Mj[i], m[i], Mj_1[i], temp1, temp);
		cotstr(Mj_1[i], str);
		printf("M%d(-1)分别为:",i+1);
		printf("%s(mod %s)\n",str,str1);
		copy(m_mult_temp, m_mult);
	}
	printf("\n");
	//计算Xj
	temp = mirvar(0);
	for (i = 0; i < GROUP_NUM; i++) {
		multiply(Mj[i], Mj_1[i], m_factor);
		multiply(m_factor, a[i], Xj[i]);
		//cotnum(Xj[i], stdout);
		//计算最终的累和
		cotstr(Xj[i], str);
		cotstr(m_mult, str1);
		printf("分别获得的X%d是:",i + 1);
		printf("%s(mod %s)\n", str, str1);
		add(Xj[i], temp, temp);
	}
	temp1 = mirvar(1);
	powmod(temp, temp1, m_mult_temp, temp);
	cotstr(temp, str);
	printf("\n计算得到X是:");
	printf("%s(mod %s)\n\n", str, str1);
	mirexit();



	return 1;
}

//主函数
int main()
{
	/* code */
	int flag, flag1;
	char str[] = "info.txt";

	while (1) {
	print_welcome();
	//输入进行的操作
	scanf("%d", &flag);
	//选择函数来判断将进行哪一个操作
	switch (flag) {
	case 1:printf("\n您选择了手动输入数据!\n\n"); input_by_hand(); break;
	case 2:printf("\n您选择了读取文件数据!\n\n"); flag1 = read_file(str); break;
	case 3:printf("\n您选择了退出!\n"); return 0;
	}
	}
	

	return 0;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值