【算法基础3】数字太大了怎么办?c/c++里的高精度加减乘除

一、高精度加法

        主要思想:通过把较大的数按位依次保存在数组里,实现大数的相加。实际操作中为了方便进位,保存时要采用小端法,从个位开始存储,即存储数7654时,a[0]存4,a[1]存5,a[2]存6,a[3]存7,倒序进行存储。定义t保存进位,从个位开始依次相加,最终运算结果的每一位的值都是A[i]+B[i]+t。结果输出时再倒序遍历数组进行输出。

       

        例题:两个特别大的数A和B求和。

#include
#include
using namespace std;

vector add(vector &A,vector &B){//对数组进行引用不需要拷贝,节省时间
	int t=0;//t中存储进位
	vector C;
	for(int i=0;i A,B;
	cin>>a>>b;
	for(int i=a.size()-1;i>=0;i--) A.push_back(a[i]-'0');//实现ASCLL码到数字的转换
	for(int i=b.size()-1;i>=0;i--) B.push_back(b[i]-'0');//必须是单引号,双引号是字符组,不能相减	
	
    auto C=add(A,B);//auto为计算机自己判断类型,也可以写成vector
	
    for(int i=C.size()-1;i>=0;i--) printf("%d",C[i]);
	return 0;
}

        注1:重点关注几个遍历中的顺序,读入数组是逆序,相加计算是顺序,输出结果是逆序。

        注2:vector是向量类型,可以容纳许多类型的数据,因此也被称为容器,尖括号内是数据类型,添加元素用类函数push_back(),读取元素类数组可以直接用下标。

二、高精度减法

        主要思想:存储和输出与大数相加相同,减法运算时定义t存储借位,当A[i]-B[i]-t<0时不够减,借1位加上10,结果存为A[i]-B[i]-t+10的个位,t更新为1;当A[i]-B[i]-t>=0时够减,结果存为A[i]-B[i]-t的个位,t更新为0。输出时还要考虑多余的0,确保不会出现"000"、“001”等情况。

        例题:两个特别大的数A和B求差。

#include
#include
using namespace std;

bool cmp(vector &A,vector &B){//自定义cmp函数比较A和B的大小
	if(A.size()!=B.size()) return A.size()>B.size();

	for(int i=A.size()-1;i>=0;i--){//【1】
		if(A[i]!=B[i]) return A[i]>B[i];
	}
	return true;//遍历完还没有返回,A=B
}

vector sub(vector &A,vector &B){
	int t=0;//t存储借位
	vector C;

	for(int i=0;i=0和t<0的两种处理情况
		if(t>=0) t=0;//够减,不用借位
		else t=1;//不够减,借位1
	}

	while(C.size()>1&&C.back()==0) C.pop_back();
    //处理冗余的0,C的最后一个值即为结果的最高位
	return C;
}

int main(){
	string a,b;
	vector A,B;
	cin>>a>>b;
	for(int i=a.size()-1;i>=0;i--) A.push_back(a[i]-'0');
	for(int i=b.size()-1;i>=0;i--) B.push_back(b[i]-'0');
		
	if(cmp(A,B)){//当A>=B时直接减
		auto C=sub(A,B);
		for(int i=C.size()-1;i>=0;i--) printf("%d",C[i]);
	} 
	else{//A=0;i--) printf("%d",C[i]);//【2】
	}
	
	return 0;
}

        【1】:A和B位数相同时,比较第一个不相等的数的大小来确定A和B的大小。注意数组内是逆序存储,比较时要从高位依次向后比较,逆序遍历。

        【2】:虽然不论A-B还是B-A,输出C的方式相同,但只能把输出写在if-else内,写到外面编译器识别不到C的定义会报错。

三、高精度乘法

        主要思想:按照多位数乘个位数的计算方式,把小数b当成个位数进行乘法运算。从个位开始遍历大数A的每一位A[i],依次与小数b进行乘法运算,最终结果C的每一位C[i]都是每次乘法运算的结果模10,进位是每次乘法运算的结果除以10。

        例题:求一个很大的数a乘一个很小的数b。

#include
#include
using namespace std;

vector mul(vector &A,int b){
	vector C;
	int t=0;//t存储进位
	for(int i=0;i A;
	string a;
	int b;
	cin>>a>>b;
	for(int i=a.size()-1;i>=0;i--) A.push_back(a[i]-'0');
	
	auto C=mul(A,b);
	
	for(int i=C.size()-1;i>=0;i--) printf("%d",C[i]);
	return 0;
}

四、高精度除法

        主要思想:从大数的最高位开始依次做除法,每次除法商保留除以b的值,进位为余数乘以10。

        例题:求一个很大的数除以一个小数的商和余数。

#include
#include
#include

using namespace std;

vector div(vector &A,int b,int &r){//r保存余数
	vector C;
	for(int i=A.size()-1;i>=0;i--){//【1】
		r=r*10+A[i];
		C.push_back(r/b);
		r%=b;//注意进位为模b
	}
	reverse(C.begin(),C.end());//C中的结果是大端存储,逆序方便后面输出
	while(C.size()>1&&C.back()==0) C.pop_back();//此处是pop_back,先逆序再除冗余0

	return C;
}

int main(){
	vector A;
	string a;
	int b;
	cin>>a>>b;
	for(int i=a.size()-1;i>=0;i--) A.push_back(a[i]-'0');
	
	int r=0;
	auto C=div(A,b,r);
	
	for(int i=C.size()-1;i>=0;i--) printf("%d",C[i]);
	cout<

        【1】:注意除法运算时是从最高位开始计算,但是为了与加法减法乘法统一,便于综合计算,存储时还是用小端法(即从最低位开始存储),计算时要逆序遍历,C中的结果是大端存储,再调用reverse()函数将结果转成小端存储,便于输出。

你可能感兴趣的:(算法基础,算法,c语言,c++)