C语言/C++实现大数四则运算

所谓大数,就是数字非常(*100)的大,不管是int还是long long int都存储不下的数,如何进行加减乘除四则运算,这种情况在计算机的运算中还是很常见的,现将大致思路写上,并附上代码以供参考。

整体思路

首先数据必然是不能以int或者long long int存储,那么只能以字符串或者字符数组的形式存储。而且实际上,以字符数组接收数据最佳,然后把字符数组转化为int数组,再对数字进行计算。

其次,联想起我们小学二年级所学的加减乘除四则运算,我们会发现一个最基本的规律:

  • 加减乘:从右往左计算
  • 除法:从左往右计算

这就提示我们,数据需要进行一下处理,因为输入的数据是不定长的,所以我们需要把数据对齐。也就是说我们需要在加减乘,将数据倒过来,个位对个位,十分位对十分位;但是在除法中,我们只要按从左往右接收数据就可。

数据结构

int数组没有不能像字符数组那样,可以直接获取长度,所以最初想法就是在转化int数组的时候,再加上一个变量len,标记数组长度。

#define MAX 1000

struct bigNum{
	int n[MAX];
	int len;
	bigNum(){
		memset(n, 0, sizeof(n));
		len = 0;
	}
};

数据处理

根据上边的思路,我们需要将char型数组转化为int型数组,而且是倒序,这样保证从个位开始对齐,方便加减乘运算,而除法只需要将char型数组转化为int型数组就可。

当然还有一些其他的工具,比如比较两个bigNum的大小,这在减法和除法上需要用到,还有除法采用的是减法思想,所以除法的数组顺序也要有个调整。

// 加减乘处理使用
bigNum transfer(char str[]){
	bigNum bn;
	bn.len = strlen(str);
	
	int i;
	for(i=0; i<bn.len; i++)
		bn.n[i] = str[bn.len-1-i] - '0';
	
	return bn;
}
// 除法处理使用
bigNum transferSort(char str[]){
	bigNum bn;
	bn.len = strlen(str);
	
	int i;
	for(i=0; i<bn.len; i++)
		bn.n[i] = str[i] - '0';
	
	return bn;
}
// 加减乘处理使用
int compare(bigNum a, bigNum b){
	if(a.len > b.len) return 1;
	else if(a.len < b.len) return -1;
	else{
		int i;
		for(i=a.len-1; i>0; i--){ //高位比较 
			if(a.n[i] > b.n[i]) return 1;
			else if(a.n[i] < b.n[i]) return -1;
			else return 0;
		}
	}
}
// 除法处理使用
int compareSort(bigNum a, bigNum b){
	if(a.len > b.len) return 1;
	else if(a.len < b.len) return -1;
	else{
		int i;
		for(i=0; i<a.len; i++){ //高位比较 
			if(a.n[i] > b.n[i]) return 1;
			else if(a.n[i] < b.n[i]) return -1;
			else return 0;
		}
	}
}
// 倒序,除法用
void reverse(int a[], int len){
	int i;	
	for(i=0; i<len/2; i++){
		int temp = a[i];
		a[i] = a[len-1-i];
		a[len-1-i] = temp;
	}	
}

大数加法

bigNum add(bigNum a, bigNum b){ // a+b
	bigNum c;
	int flag = 0;
	int len = (a.len > b.len) ? a.len : b.len;
	int i;
	for (i=0; i<len; i++){
		int temp = a.n[i] + b.n[i] + flag;
		flag = (temp >= 10) ? 1 : 0; 
		c.n[c.len++] = temp % 10; 
	}
	// 处理进位情况
	if(flag != 0)
		c.n[c.len++] = 1;  
		
	return c;	
}

大数减法

bigNum sub(bigNum a, bigNum b){ // a-b 或 a+(-b) 
	bigNum c;
	int len = (a.len > b.len) ? a.len : b.len;	
	int i;
	for(i=0; i<len; i++){
		if(a.n[i]<b.n[i]){ 
			a.n[i+1]--;   //借一
			a.n[i] += 10; //当十 
		}
		c.n[c.len++] = a.n[i] - b.n[i]; 
	}
	// 去除高位0 112-111=001,但是要保证有一位数 
	while(c.n[c.len-1]==0 && c.len>1)
		c.len--;
		 
	return c; 
}

大数乘法

// 高精度与低精度乘法运算,为高精度乘法运算使用
bigNum sigMul(bigNum a, int b){  // 低精度 b 
	bigNum c;
	int flag = 0;
	int i;
	for(i=0; i<a.len; i++){
		int temp = a.n[i]*b + flag;
		c.n[c.len++] = temp % 10; 
		flag = temp/10;
	}
	while(flag){
		c.n[c.len++] = flag % 10;
		flag /= 10;
	}
	return c;
}
// 数组移位操作
bigNum move(bigNum a, int index){
	bigNum b = bigNum();
	int i;
	b.len = a.len + index;
	for(i=0; i<a.len; i++){
		b.n[i+index] = a.n[i];
	}
	return b;
}
// 高精度乘法运算
bigNum mul(bigNum a, bigNum b){  // 高精度 b 
	bigNum c = bigNum();
	int i;
	for(i=0; i<b.len; i++){
		bigNum temp =  sigMul(a, b.n[i]);
		bigNum temp_move = move(temp,i);
		c = add(c, temp_move);
	}
	return c;
}

大数除法

其实可以用逆序,但是当前正序思维好捋一点。减法暂时实现了除数是个位数,多位的还没来得及调试,但是考完试不太想debug,先放个坑在这里,啥时候记得补了,再回来填。欢迎大佬进行指导。

// 高精度与低精度除法运算  逆序
bigNum sigDiv(bigNum a, int b, int &r){ 
	bigNum c;
	c.len = a.len;
	int i;
	for(i=a.len-1; i>0; i--){ // 高位开始 
		r =  r*10 + a.n[i];
		if(r<b) c.n[i] = 0;
		else{
			c.n[i] = r/b;
			r %= b;
		}
	}
	while(c.n[c.len-1]==0 && c.len>1)
		c.len--;
		
	return c;
}
// 高精度除法运算
bigNum div(bigNum a, bigNum b, bigNum r){ // 正序   计算大数 a/b 
	bigNum c;
	c.len = a.len;
	
	int i; 
	for(i=0; i<a.len; i++){ // 高位开始 
		r.n[r.len++] = a.n[i];
		int flag = compareSort(r, b);
			
		if(flag == -1) c.n[i] = 0;
		else if(flag == 0){
			 c.n[i] = 1;
			 // 无需翻转也能为0 
			 r = sub(r, b);
			 r.len = 0;  // 结果为0,长度是1,这里需要处理,否则会多一位
		} else{
			// 做减法
			int index = 0;
			while(compareSort(r, b)==1){
				reverse(r.n, r.len);
				reverse(b.n, b.len);
				r = sub(r, b);
				reverse(r.n, r.len);
				index++;
			} 
			c.n[i] = index;	
		}	
	}
	// 处理开头 b.n-1 个0 ,循环左移
	while(c.n[0]==0 && c.len>1){
		int k;
		for(k=0; k<c.len-1; k++)
			c.n[k] = c.n[k+1];
		c.len--;
	}
	
	return c;
} 

整体代码

#include<iostream>
#include<cstring> 
#include<stdio.h>
#include<string.h>
using namespace std;

#define MAX 1000

struct bigNum{
	int n[MAX];
	int len;
	bigNum(){
		memset(n, 0, sizeof(n));
		len = 0;
	}
};

void screenPrint(bigNum a){
	int i;
	for(i=a.len-1; i>=0; i--)
		printf("%d", *(a.n+i)); //printf("%d", a.n[i]);
	printf("\n");
}
void print(bigNum a){
	int i;
	for(i=0; i<a.len; i++)
		printf("%d", *(a.n+i)); //printf("%d", a.n[i]);
	printf("\n");
}
bigNum transfer(char str[]){
	bigNum bn;
	bn.len = strlen(str);
	
	int i;
	for(i=0; i<bn.len; i++)
		bn.n[i] = str[bn.len-1-i] - '0';
	
	return bn;
}

bigNum transferSort(char str[]){
	bigNum bn;
	bn.len = strlen(str);
	
	int i;
	for(i=0; i<bn.len; i++)
		bn.n[i] = str[i] - '0';
	
	return bn;
}

void reverse(int a[], int len){
	int i;	
	for(i=0; i<len/2; i++){
		int temp = a[i];
		a[i] = a[len-1-i];
		a[len-1-i] = temp;
	}	
}

bigNum add(bigNum a, bigNum b){ // a+b
	bigNum c;
	int flag = 0;
	int len = (a.len > b.len) ? a.len : b.len;
	int i;
	for (i=0; i<len; i++){
		int temp = a.n[i] + b.n[i] + flag;
		flag = (temp >= 10) ? 1 : 0; 
		c.n[c.len++] = temp % 10; 
	}
	if(flag != 0)
		c.n[c.len++] = 1;
		
	return c;	
}

bigNum sub(bigNum a, bigNum b){ // a-b 或 a+(-b) 
	bigNum c;
	int len = (a.len > b.len) ? a.len : b.len;	
	int i;
	for(i=0; i<len; i++){
		if(a.n[i]<b.n[i]){ 
			a.n[i+1]--;   //借一
			a.n[i] += 10; //当十 
		}
		c.n[c.len++] = a.n[i] - b.n[i]; 
	}
	// 去除高位0 112-111=001,但是要保证有一位数 
	while(c.n[c.len-1]==0 && c.len>1)
		c.len--;
		 
	return c; 
}

int compare(bigNum a, bigNum b){
	if(a.len > b.len) return 1;
	else if(a.len < b.len) return -1;
	else{
		int i;
		for(i=a.len-1; i>0; i--){ //高位比较 
			if(a.n[i] > b.n[i]) return 1;
			else if(a.n[i] < b.n[i]) return -1;
			else return 0;
		}
	}
}

int compareSort(bigNum a, bigNum b){
	if(a.len > b.len) return 1;
	else if(a.len < b.len) return -1;
	else{
		int i;
		for(i=0; i<a.len; i++){ //高位比较 
			if(a.n[i] > b.n[i]) return 1;
			else if(a.n[i] < b.n[i]) return -1;
			else return 0;
		}
	}
}

bigNum sigMul(bigNum a, int b){  // 低精度 b 
	bigNum c;
	int flag = 0;
	int i;
	for(i=0; i<a.len; i++){
		int temp = a.n[i]*b + flag;
		c.n[c.len++] = temp % 10; 
		flag = temp/10;
	}
	while(flag){
		c.n[c.len++] = flag % 10;
		flag /= 10;
	}
	return c;
}

bigNum move(bigNum a, int index){
	bigNum b = bigNum();
	int i;
	b.len = a.len + index;
	for(i=0; i<a.len; i++){
		b.n[i+index] = a.n[i];
	}
	return b;
}

bigNum mul(bigNum a, bigNum b){  // 高精度 b 
	bigNum c = bigNum();
	int i;
	for(i=0; i<b.len; i++){
		bigNum temp =  sigMul(a, b.n[i]);
		bigNum temp_move = move(temp,i);
		c = add(c, temp_move);
	}
	return c;
}

bigNum sigDiv(bigNum a, int b, int &r){ 
	bigNum c;
	c.len = a.len;
	int i;
	for(i=a.len-1; i>0; i--){ // 高位开始 
		r =  r*10 + a.n[i];
		if(r<b) c.n[i] = 0;
		else{
			c.n[i] = r/b;
			r %= b;
		}
	}
	while(c.n[c.len-1]==0 && c.len>1)
		c.len--;
		
	return c;
}

bigNum div(bigNum a, bigNum b, bigNum r){ // 正序   计算大数 a/b 
	bigNum c;
	c.len = a.len;
	//r.len = b.len+1; // a.len - b.len;
	
	int i; // 控制 a c
	int j = 0;  // 控制 c 
	
	for(i=0; i<a.len; i++){ // 高位开始 
		r.n[r.len++] = a.n[i];
		int flag = compareSort(r, b);
			
		if(flag == -1) c.n[i] = 0;
		else if(flag == 0){
			 c.n[i] = 1;
			 // 无需翻转也能为0 
			 r = sub(r, b);
			 r.len = 0;
		} else{
			// 做减法
			int index = 0;
			while(compareSort(r, b)==1){
				reverse(r.n, r.len);
				reverse(b.n, b.len);
				r = sub(r, b);
				reverse(r.n, r.len);
				index++;
			} 
			c.n[i] = index;	
		}	
	}
	
	while(c.n[0]==0 && c.len>1){
		int k;
		for(k=0; k<c.len-1; k++)
			c.n[k] = c.n[k+1];
		c.len--;
	}
	
	return c;
} 

int main(){
	char str1[MAX], str2[MAX];
	scanf("%s%s", str1, str2);
	// ========================加减乘============================
	// 反序,加减乘都是从右到左 
	//bigNum bn_str1 = transfer(str1);
	//bigNum bn_str2 = transfer(str2);
	
	//bigNum bn_add = add(bn_str1, bn_str2); 
	//screenPrint(bn_add); 
	
	/*
	bigNum bn_sub;
	if(compare(bn_str1,n_str2) == 1){ //  a>b
		bn_sub = sub(bn_str1, bn_str2); 	 
	}else if(compare(bn_str1, bn_str2) == -1){ //  a<b
		bn_sub = sub(bn_str2, bn_str1); 
		printf("-");
		
	} else{ // a=b 
		bn_sub = sub(bn_str1, bn_str2);
	}
	screenPrint(bn_sub);	
	*/
	
	// ========================除法============================	
	// 正序,除是从左到右  
	bigNum bn_str1 = transferSort(str1);
	bigNum bn_str2 = transferSort(str2);
	
	//reverse(bn_str1.n, bn_str1.len);
	//print(bn_str1);
	
	
	bigNum bn_r = bigNum();
	if(compareSort(bn_str1, bn_str2) == 1){ //  a>b
		bigNum bn_div = div(bn_str1, bn_str2, bn_r);
		print(bn_div);
	} 
	else if(compareSort(bn_str1, bn_str2) == -1) printf("0"); //  a<b
	else printf("1"); // a=b 
		
	return 0;
} 

不太想码字了,刚考完密码学第一次考试,人生啊,就是如此艰难。溜了溜了,睡觉。

猜你喜欢

转载自blog.csdn.net/qq_37195179/article/details/105786857
今日推荐