【知识点6】大整数运算(高精度整数运算)⭐⭐⭐⭐⭐

在这里插入图片描述
大整数又称为高精度整数

1. 大整数的存储

使用数组即可。

注意:

  • 整数的高位存储在数组的高位,整数的低位存储在数组的低位。
  • 由于字符串“%s”读入会实际上是逆位存储的,因此要在读入之后需要进行反转。

为了方便随时获取大整数的长度,一般都会定义一个int型变量len来记录其长度,并和数组合成一个结构体:

struct bign{
	int d[1000];
	int len;
};

注意:

  • 在定义结构体变量之后,需要马上初始化结构体,我们使用构造函数
  • 而且一定要确保所有位数在一开始都全部被赋值为0,不然后面运算会出错。
struct bign{
	int d[1000];
	int len;
	bign(){
		memset(d,0,sizeof(d));
		len = 0;
	} 
};

而在输入大整数时,一般都是先用字符串读入,然后再把字符串另存为至bign结构体

bign change(char str[]){
	bign a;
	a.len = strlen(str);
	for(int i=0;i<a.len;i++){
		a.d[i] = str[a.len -i -1] - '0';
	}
	return a;
}

如果要比较两个bign变量的大小,思路是:

  1. 比长度;(要保证没有前导0)
  2. 依次比高位。

代码如下:

int compare(bign a,bign b){
	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;
	}
}

接下来主要介绍四个运算:

1. 高精度与高精度之间的加法;
2. 高精度与高精度之间的减法;
3. 高精度与低精度之间的乘法;
4. 高精度与低精度之间的除法。

至于高精度与高精度之间的乘除,考试一般不涉及。

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

2.1 高精度加法

在这里插入图片描述

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; 
	}
	
	//如果最后进位不为0,则直接赋给结果的最高位!!! 
	if(carry != 0){
		c.d[c.len++] = carry;
	}
	
	return c; 
}

注意:

  • 如果最后进位不为0,则直接赋给结果的最高位
  • 上述是两个正数的加法,如果是负数,则是减法了。

2.2 高精度减法

在这里插入图片描述

bign sub(bign a,bign b){
	bign c;
	for(int i=0;i<a.len||i<b.len;i++){
		
		if(a.d[i] < b.d[i]){	//如果不够减 
			a.d[i+1]--;
			a.d[i] += 10;
		}
		
		c.d[c.len++] = a.d[i] - b.d[i]; 
	}
	
	while(c.len -1 >= 1 && c.d[c.len - 1] == 0){
		c.len--;	//去除高位的0,同时至少保留一位最低位 
	}
	
	return c;
}

注意:

  • 减法后高位可能有多余的0,要忽略它们,但也要保证结果至少有一位数,即0。
  • 这里只是大数减小数,如果是小数减大数,要先大数减小数,再取负号。⭐⭐⭐⭐⭐

2.3 高精度与低精度的乘法💢

在这里插入图片描述

bign multi(bign a,int b){
	bign c;
	int carry = 0;	//进位
	for(int i=0;i<a.len;i++){
		int tmp = a.d[i] * b + carry;
		c.d[c.len++] = tmp % 10;	//个位作为该位的结果 
		carry = temp / 10; 			//高位作为新的进位 
	}
	while(carry != 0){
		c.d[c.len++] = carry % 10;
		carry /= 10;
	}
	return c; 
}

注意:

  • 将低精度整数看作整体,因为高精度的话就会导致溢出的~。
  • 还有就是正负数,先保存符号,后面再运算。

2.4 高精度与低精度的除法💢

在这里插入图片描述

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){	//不够除,该位为0 
			c.d[i] = 0;
		}else{	//够除 
			c.d[i] = r / b;	//商 
			r = r % b;	//获得新的余数 
		} 
		/**也可以直接这样写
		//这里面包含了两种情况 
		c.d[i] = r / b;
		r = r % b; 
		**/
	}
	
	while(c.len-1 >= 1 && c.d[c.len-1] == 0){
		c.len--;	//去除高位的0,同时至少保留一位最低位 
	}
	
	return c; 
}

注意:

  • 由于被除数的每一位和商的每一位都是一一对应的,因此先令长度相等
  • 从高位开始;
  • 要注意最后的高位可能有多余的0,要忽视它们,但也要保证结果至少有一位数。

2.5 高精度与高精度的乘法

模板的思想很简单:
一开始并不考虑进位,只是单纯地得到每一位上的数字。然后再统一地进行进位操作。

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn = 1e4+10;

struct bign{
	int d[maxn];
	int len;
	bign(){
		fill(d,d+maxn,0);
		len=0;
	}
};

char str1[1010];
char str2[1010];

bign change(char str[]){
	int len = strlen(str);
	bign a;
	for(int i=0;i<len;i++){
		a.d[i] = str[len-1-i]-'0';
		a.len++;
	}
	return a;
}

bign multi(bign a,bign b){
	bign c;
	c.len=a.len+b.len;//初始化长度
	
	for(int i=0;i<a.len;i++){
		for(int j=0;j<b.len;j++){
			c.d[i+j]+=a.d[i]*b.d[j];
		}
	}
	
	//然后进行进位
	for(int i=0;i<c.len;i++){//注意这个长度 
		c.d[i+1] += c.d[i]/10;
		c.d[i] = c.d[i]%10;
	}
	
	while(c.len-1>=1&&c.d[c.len-1]==0){
		c.len--;
	}
	return c;
	
}

int main(){
	freopen("input.txt","r",stdin);
	while(scanf("%s %s",str1,str2)!=EOF){
		bign a = change(str1);
		bign b = change(str2);
		
		bign c = multi(a,b);
		
		for(int i=0;i<c.len;i++){
			printf("%d",c.d[c.len-1-i]);
		} 

		printf("\n"); 
	}
	return 0;
}

2.6 高精度与高精度的除法

对于高精度与高精度的除法,需要考虑到多少倍够除的情况,这里使用的思想就是不断地做高精度减法,这样就能实现了。
具体参考王道书上的写法。

2.7 高精度与低精度的取余

在这里插入图片描述

//大数取余
LL Qpow_mod(){
	LL ans=0;
	int n=strlen(a);
	for(int i=0;i<n;i++)
		ans=(ans*10+(a[i]-'0'))%mod;
	return ans;
}

int main(){ 
	scanf("%s",a);
	LL b=Qpow_mod();
	printf("%lld\n",b);
    return 0;
}

3. 题型训练

  1. 【PAT B1017】A除以B
  2. 【PAT A1023】Have Fun with Numbers
  3. a+b——华科
  4. N的阶乘——清华
  5. ⭐进制转换2——清华
  6. LeetCode 2. Add Two Numbers
  7. 【高精度加法】PAT A1024 Palindromic Number
  8. LeetCode 989. Add to Array-Form of Integer(高精度与int类型整数的加法,有两种做法)

4. 参考文档

  1. 算法笔记
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值