大整数的四则运算(高精度运算)

6 篇文章 0 订阅
1 篇文章 0 订阅

1.大整数的存储

	大整数存储用于基本数据类型无法存储的高精度整数,整数的高位存在数组的高位,整数的低位存在数组的低位。

(1)大整数初始化结构体代码:

struct bign{
//存储大整数,这里设置可存储的最大为1000位
	int d[1000];
	int len;
	bign(){//初始化结构体
	//memset将数组d的所有元素赋值为0
		memset(d,0,sizeof(d));
		len = 0;
	}
};

(2)输入大整数时,先用字符串读入,再把字符串另存为到bign结构体。由于使用char数组读入时,整数的高位会变成数组的低位,因此为了让整数在bign中为顺位存储,得让字符串逆着赋值给d数组。

代码:

bign change(char str[]){//将整数转化为bign 
	bign a;
	a.len = strlen(str);
	//bign的长度就是字符串的长度 
	for(int i = 0 ; i < a.len ; i ++){
		//逆着赋值
		a.d[i] = str[a.len - i - 1] - '0';		 
	}
	return a;
}

(3)大整数比较
如果比较两个bign变量的大小:先判断两者的len大小,如果不相等,长的为大;若相等,则依次从高位到低位进行比较,知道出现某一位不等,大的数字为大。

代码:

int compare(bign a, bign b){
//比较ab大小,前者大返回1,后者大返回-1,否则返回0 
	if(a.len < b.len){
		return -1;
	}
	else if(a.len > b.len){
		return 1;
	} 
	else{
		for(int i = a.len - 1 ; i >= 0 ; i ++){
			if(a.d[i] > b.d[i]){
				return 1;
			}
			else if(a.d[i] < b.d[i]){
				return -1;
			}
		}
	} 
	return 0;
}

2.高精度加法
对一位进行加法,就是将该位上的两个数字与进位相加,得到的结果作为该位结果,取十位数作为新的进位。然后从低位到高位重复该步骤。

代码:

bign add(bign a, bign b){//加法 
	bign c;
	int carry = 0;//carry是进位
	for(int i = 0 ; i < a.len || i < b.len ; i ++){//以较长的为界限 
		int temp = a.d[i] + b.d[i] + carry;//两个对应位与进位相加
		c.d[c.len++] = temp % 10;//个位数为该位结果
		carry = temp / 10;//十位数为新的进位 
	} 
	if(carry != 0){//最后进位不为0,直接赋值给结果的最高位 
		c.d[c.len++] = carry;
	} 
	return c;
}

3.高精度减法
对某一步,比较被减位和减位,若不够减,则令被减位的高位减1,被减位加10再进行减法;如果够减,则直接减。最后一步时,要注意减法后高位可能有多余的0,要去除它们,但也要保证结果至少有1位数。

代码:

bign sub(bign a, bign b){//减法 
	bign c;
	int carry = 0;//carry是退位
	for(int i = 0 ; i < a.len || i < b.len ; i ++){//以较长的为界限 
		int temp = a.d[i] - b.d[i] - carry; //存储当前位 
		if(temp >= 0){//没有借位,carry = 0 
			c.d[c.len++] = temp;
			carry = 0;
		}else{//不够减 , 高位借1, 低位加10 
			c.d[c.len++] = temp + 10;
			carry += 1; 
		} 
	}
	while(c.len - 1 >= 1 && c.d[c.len - 1] == 0){//除去最高位的0,保留最低一位 
		c.len --;
	} 
	return c;
}

4.高精度与低精度的乘法
取bign 的某位与int型整体进行相乘,再与进位相加,所得结果的个位数作为该位结果,高位部分作为新的进位。

代码:

bign multi(bign a, int b){//高精度与低精度的乘法 
	bign c;
	int carry = 0;//进位
	for(int i = 0 ; i < a.len ; i ++){
		int temp = a.d[i]*b + carry;	//当前存储值 
		c.d[c.len++] = temp % 10;	//个位作为当前位的结果 
		carry = temp / 10;	//更高位的进位 
	}
	while(carry != 0){
		c.d[c.len++] = carry % 10;
		carry /= 10;
	} 
	return c;
}

5.高精度与低精度的除法
上一步的余数乘以10加上该步的位的值,得到该步临时的被除数,将其与除数比较;若不够除,则该位的商为0;若够除,商即为对应的商,余数即为对应的余数。最后一步要注意减法后高位可能有多余的0,要去除它们,但也要保证结果至少有一位数。

代码:

bign divide(bign a, int b, int& r){
//高精度与低精度的除法 
//r为余数 
	bign c;
	c.len = a.len;	//被除数的每一位和商的每一位是一一对应的,因此先令长度相等
	for(int i = a.len -1 ; i >= 0 ; i --){	//从高位开始 
		r = r * 10 + a.d[i];//和上一位遗留的余数组合,临时的被除数 
		if(r < b)	c.d[i] = 0;//不够除,该位为0
		else{	//够除 
			c.d[i] = r / b;	//商
			r = r % b;	//新的余数 
		} 
	} 
	while(c.len - 1 >= 1 && c.d[c.len - 1] == 0){
		c.len --;	//去除高位的0,至少保留一位最低位 
	} 
	return c;
}

6.总代码示例

#include<iostream>
#include<cstdio>
#include<cstring> 
using namespace std;

struct bign{
	int d[1000];
	int len;
	bign(){
		memset(d,0,sizeof(d));
		len = 0;
	}
};

bign change(char str[]){//将整数转化为bign 
	bign a;
	a.len = strlen(str);	//bign的长度就是字符串的长度 
	for(int i = 0 ; i < a.len ; i ++){
		a.d[i] = str[a.len - i - 1] - '0';//逆着赋值 
	}
	return a;
}

bign add(bign a, bign b){//加法 
	bign c;
	int carry = 0;//carry是进位
	for(int i = 0 ; i < a.len || i < b.len ; i ++){//以较长的为界限 
		int temp = a.d[i] + b.d[i] + carry;//两个对应位与进位相加
		c.d[c.len++] = temp % 10;//个位数为该位结果
		carry = temp / 10;//十位数为新的进位 
	} 
	if(carry != 0){//最后进位不为0,直接赋值给结果的最高位 
		c.d[c.len++] = carry;
	} 
	return c;
}

int compare(bign a, bign b){//比较ab大小,前者大返回1,后者大返回-1,否则返回0 
	if(a.len < b.len){
		return -1;
	}
	else if(a.len > b.len){
		return 1;
	} 
	else{
		for(int i = a.len - 1 ; i >= 0 ; i ++){
			if(a.d[i] > b.d[i]){
				return 1;
			}
			else if(a.d[i] < b.d[i]){
				return -1;
			}
		}
	} 
	return 0;
}
 
bign sub(bign a, bign b){//减法 
	bign c;
	int carry = 0;//carry是退位
	for(int i = 0 ; i < a.len || i < b.len ; i ++){//以较长的为界限 
		int temp = a.d[i] - b.d[i] - carry; //存储当前位 
		if(temp >= 0){//没有借位,carry = 0 
			c.d[c.len++] = temp;
			carry = 0;
		}else{//不够减 , 高位借1, 低位加10 
			c.d[c.len++] = temp + 10;
			carry += 1; 
		} 
	}
	while(c.len - 1 >= 1 && c.d[c.len - 1] == 0){//除去最高位的0,保留最低一位 
		c.len --;
	} 
	return c;
}

bign multi(bign a, int b){//高精度与低精度的乘法 
	bign c;
	int carry = 0;//进位
	for(int i = 0 ; i < a.len ; i ++){
		int temp = a.d[i]*b + carry;	//当前存储值 
		c.d[c.len++] = temp % 10;	//个位作为当前位的结果 
		carry = temp / 10;	//更高位的进位 
	}
	while(carry != 0){
		c.d[c.len++] = carry % 10;
		carry /= 10;
	} 
	return c;
} 

bign divide(bign a, int b, int& r){//高精度与低精度的除法 //r为余数 
	bign c;
	c.len = a.len;	//被除数的每一位和商的每一位是一一对应的,因此先令长度相等
	for(int i = a.len -1 ; i >= 0 ; i --){	//从高位开始 
		r = r * 10 + a.d[i];//和上一位遗留的余数组合,临时的被除数 
		if(r < b)	c.d[i] = 0;//不够除,该位为0
		else{	//够除 
			c.d[i] = r / b;	//商
			r = r % b;	//新的余数 
		} 
	} 
	while(c.len - 1 >= 1 && c.d[c.len - 1] == 0){
		c.len --;	//去除高位的0,至少保留一位最低位 
	} 
	return c;
}
void print(bign a){//输出bign 
	for(int i = a.len - 1 ; i >= 0 ; i --){
		cout<<a.d[i];
	} 
} 

int main(){
	char s1[1000],s2[1000];
	int c,r = 0;
	scanf("%s%d",s1,&c); 
	//scanf("%s%s",s1,s2);
	bign a = change(s1);
	print(divide(a, c, r));除法 
	cout<<endl;
	cout<<r;//余数
	
	
	 
	//print(multi(a,c));乘法 
	//bign b = change(s2);
	
	
	
	/*int k = compare(a,b);//正负系数
	if(k > 0){//说明a > b 
		print(sub(a,b));
	}else if(k < 0){
		cout<<"-";
		print(sub(b,a));
	}else{
		cout<<0;
	}	*///减法 

	
	//cout<<endl;
	//print(add(a,b)); 加法 
	
	return 0;
} 
  • 1
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值