C++学习笔记——高精度加法与减法

新人,第一次写,可能会出现各种错误,望各位多多指教。 洛谷1601 题目描述 高精度加法,相当于 a+b problem,不用考虑负数。 输入格式 分两行输入。a,b≤10的500次方。 输出格式 输出只有一行,代表a+b 的值

a+b问题一直以来都被视为最为简单的初学者题目之一。但是,当a+b的数值过大,超过了long long的最大范围时,我们又该如何处理a+b问题呢?本章将对其进行探讨与讲解。

 首先,我们很容易想到用字符数组进行读入,读入函数如下:

#include<bits/stdc++.h>
using namespace std;
char a[505],b[505];
void read(){
scanf("%s",a+1);
scanf("%s",b+1);
}

然后,我们要考虑如何进行两个字符数组的加法运算

显然,我们还需要还需要开int类型的数组对字符数组中各个数位上的数进行储存,对代码进行增添后如下:

#include<bits/stdc++.h>
using namespace std;
char a[505],b[505];
int lena,lenb;
int aint[505],bint[505];//开int数组
void read(){
scanf("%s",a+1);
lena=strlen(a+1);//strlen函数记录字符长度
scanf("%s",b+1);
lenb=strlen(b+1);//
for(int i=1;i<=lena;i++){
aint[i]=a[i]-48;//-48是为了将字符转变为数字。在ACII码中,1对应49;
}
for(int i=1;i<=lenb;i++){
bint[i]=b[i]-48;
}
}//read函数定义完毕

至此,a和b两个数均由int数组从高位向低位存储。

我们开始正式进行加法运算,先开一个int类型的数组对a+b的和的各个数位对应的数进行存储

#include<bits/stdc++.h>
using namespace std;
char a[505],b[505];
int lena,lenb;
int aint[505],bint[505];//开int数组
void read(){
scanf("%s",a+1);
lena=strlen(a+1);//strlen函数记录字符长度
scanf("%s",b+1);
lenb=strlen(b+1);//
for(int i=1;i<=lena;i++){
aint[i]=a[i]-48;//-48是为了将字符转变为数字。在ACII码中,1对应49;
}
for(int i=1;i<=lenb;i++){
bint[i]=b[i]-48;
}
}//read函数定义完毕
int cint[505];

由于竖式运算中,我们是从低位开始算起的,满十进一,所以我们进行竖式加法运算时要倒序着加。新定义一个add函数:

#include<bits/stdc++.h>
using namespace std;
char a[505],b[505];
int lena,lenb;
int aint[505],bint[505];//开int数组
void read(){
scanf("%s",a+1);
lena=strlen(a+1);//strlen函数记录字符长度
scanf("%s",b+1);
lenb=strlen(b+1);//
for(int i=1;i<=lena;i++){
aint[i]=a[i]-48;//-48是为了将字符转变为数字。在ACII码中,1对应49;
}
for(int i=1;i<=lenb;i++){
bint[i]=b[i]-48;
}
}//read函数定义完毕
int cint[505];
void add(){
	int x;//x用来满十进一看留多少
	int lenc=lenb;//lenc用来记录和的长度 
	if(lena>lenb)lenc=lena; 
    else lenc=lenb;
	for(int i=lenc;i>=1;i--){
		cint[i]=
	} 
	
}

准备从个位开始a+b时突然出现了问题。lena与lenb不一定相等,所以需要对前面的程序进行修改。改成从低位向高位储存数字

#include<bits/stdc++.h>
using namespace std;
char a[505],b[505];
int lena,lenb;
int aint[505],bint[505];//开int数组
void read(){
scanf("%s",a+1);
lena=strlen(a+1);//strlen函数记录字符长度
scanf("%s",b+1);
lenb=strlen(b+1);//
for(int i=lena;i>=1;i--){
aint[i]=a[lena-i+1]-48;//-48是为了将字符转变为数字。在ACII码中,1对应49;
}
for(int i=lenb;i>=1;i--){
bint[i]=b[lenb-i+1]-48;//注意从低位向高位储存,否则后面的运算会出现问题。 
}
}//read函数定义完毕
int cint[505];
int lenc=lenb;//lenc用来记录和的长度 
void add(){
	int x=0;//x用来满十进一看留多少
	if(lena>lenb)lenc=lena; 
    else lenc=lenb;
	for(int i=1;i<=lenc;i++){//从低位开始a+b;
		if((aint[i]+bint[i]+x)<10){
		cint[i]=aint[i]+bint[i]+x;
		x=0;
		continue; 
		}
		if((aint[i]+bint[i]+x)>=10){
		cint[i]=(aint[i]+bint[i]+x)%10;
		x=1;
		continue;}//考虑是否进位;
		if(i==lenc&&(aint[i]+bint[i]+x)>=10){
			lenc++;
			cint[lenc]=1;
			break;//考虑加到最高位的特殊情况 
		}
	} 
	}//加完了!!!

最后就很简单了。

#include<bits/stdc++.h>
using namespace std;
char a[505],b[505];
int lena,lenb;
int aint[505],bint[505];//开int数组
void read(){
scanf("%s",a+1);
lena=strlen(a+1);//strlen函数记录字符长度
scanf("%s",b+1);
lenb=strlen(b+1);//
for(int i=lena;i>=1;i--){
aint[i]=a[lena-i+1]-48;//-48是为了将字符转变为数字。在ACII码中,1对应49;
}
for(int i=lenb;i>=1;i--){
bint[i]=b[lenb-i+1]-48;//注意从低位向高位储存,否则后面的运算会出现问题。 
}
}//read函数定义完毕
int cint[505];
int lenc=lenb;//lenc用来记录和的长度 
void add(){
	int x=0;//x用来满十进一看留多少
	if(lena>lenb)lenc=lena; 
    else lenc=lenb;
	for(int i=1;i<=lenc;i++){//从低位开始a+b;
		if((aint[i]+bint[i]+x)<10){
		cint[i]=aint[i]+bint[i]+x;
		x=0;
		continue; 
		}
		if((aint[i]+bint[i]+x)>=10){
		cint[i]=(aint[i]+bint[i]+x)%10;
		x=1;
		continue;}//考虑是否进位;
		if(i==lenc&&(aint[i]+bint[i]+x)>=10){
			lenc++;
			cint[lenc]=1;
			break;//考虑加到最高位的特殊情况 
		}
	} 
	}//加完了!!!
void print(){
	for(int i=lenc;i>=1;i--){
		printf("%d",cint[i]);//输出函数 
	}
} 
int main(){
	read();
	add();
	print();
	return 0;//大功告成! 
} 

但是,问题又来了。

 有一组测试结果是错误的。拿到测试数据后,我发现了问题所在。我们定义的add函数中对于最高位相加是否进一位的if判断语句应当提前,否则会收到continue语句的影响,导致出错。

 对add函数中if语句的位置进行调整后·,完整代码如下:

#include<bits/stdc++.h>
using namespace std;
char a[505],b[505];
int lena,lenb;
int aint[505],bint[505];//开int数组
void read(){
scanf("%s",a+1);
lena=strlen(a+1);//strlen函数记录字符长度
scanf("%s",b+1);
lenb=strlen(b+1);//
for(int i=lena;i>=1;i--){
aint[i]=a[lena-i+1]-48;//-48是为了将字符转变为数字。在ACII码中,1对应49;
}
for(int i=lenb;i>=1;i--){
bint[i]=b[lenb-i+1]-48;//注意从低位向高位储存,否则后面的运算会出现问题。 
}
}//read函数定义完毕
int cint[505];
int lenc=lenb;//lenc用来记录和的长度 
void add(){
	int x=0;//x用来满十进一看留多少
	if(lena>lenb)lenc=lena; 
    else lenc=lenb;
	for(int i=1;i<=lenc;i++){//从低位开始a+b;
	if(i==lenc&&(aint[i]+bint[i]+x)>=10){
			lenc++;
			cint[lenc]=1;
			break;//考虑加到最高位的特殊情况 
		}
		if((aint[i]+bint[i]+x)<10){
		cint[i]=aint[i]+bint[i]+x;
		x=0;
		continue; 
		}
		if((aint[i]+bint[i]+x)>=10){
		cint[i]=(aint[i]+bint[i]+x)%10;
		x=1;
		continue;}//考虑是否进位;
		
	} 
	}//加完了!!!
void print(){
	for(int i=lenc;i>=1;i--){
		printf("%d",cint[i]);//输出函数 
	}
} 
int main(){
	read();
	add();
	print();
	return 0;//大功告成! 
} 

改对了!

高精度减法与高精度加法大同小异,我们直接上代码

#include<bits/stdc++.h>
using namespace std;
char a[505],b[505];
int aint[505],bint[505],cint[505];
int lena,lenb,lenc;
void read(){
	scanf("%s",a+1);
	scanf("%s",b+1);
	lena=strlen(a+1);
	lenb=strlen(b+1);
	for(int i=1;i<=lena;i++){
		aint[i]=a[lena-i+1]-48;
	}
	for(int i=1;i<=lenb;i++){
		bint[i]=b[lenb-i+1]-48;//从个位向最高位存储 
	}
} 
void dec(){
	if(lena>lenb||(lena==lenb&&strcmp(a+1,b+1)>=0)){
		for(int i=1;i<=lena;i++){
			if(aint[i]-bint[i]<0){
			cint[i]=aint[i]-bint[i]+10;
		    aint[i+1]--;
		}
			else cint[i]=aint[i]-bint[i];
		}
	}
	if(lena<lenb||(lena==lenb&&strcmp(a+1,b+1)<0)){
		lenc=lenb;
		for(int i=1;i<=lenc;i++){
			if(bint[i]-aint[i]<0){
			cint[i]=bint[i]-aint[i]+10;
		    bint[i+1]--;
		}
			else cint[i]=bint[i]-aint[i];
		}
		while(cint[lenc]==0){
		lenc--;}
	}
}
void print(){
	if(lena>lenb||(lena==lenb&&strcmp(a+1,b+1)>=0)){
	for(int i=lena;i>=1;i--){
		printf("%d",cint[i]);
		}
	}
	if(lena<lenb||(lena==lenb&&strcmp(a+1,b+1)<0))	{
        printf("-");
		for(int i=lenc;i>=1;i--){
		printf("%d",cint[i]);}
	}
	}
int main(){
	read();
	dec();
	print();
	return 0;
}

不过,需要注意的是strcmp函数的应用(比较字符串大小)以及前导0的去除。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值