【C++】详解高精度加法、高精度减法、高精度乘法、高精度除法代码

目录

1、引入

2、入门思路

3、数的存储

4、高精度加法

5、高精度减法

6、高精度乘法

7、高精度除法


1、引入

        在进行大整数运算中,因为在C++/C中整数最大也就是unsigned long long也就才(1e19+8e18)位,如果要几百位的相加减就不行了,所以就要用高精度了,这里只在C++/C上使用有价值,在例如python、Java语言上无需写此算法,python可以无限大,Java里有相关库可以引入。

2、入门思路

        我们如何制作一个算法,让其可以在C++/C中可以进行理论上无限位数的数进行运算,我们试想可以把数存储在数组中,然后根据我们手算的思路,操作数组来进行运算,如下图所示:

3、数的存储

        这里数的存储呢需要进行逆序存储,因为逆序存储方面进位。以加法为例所示:

 



4、高精度加法

                我们通过手算的规律可以知道,因为随时可能存在例如(9+1)这的进位,则需要设置一个变量存储是否有进位。如果有进位。那么在下一次运算的时候就加上它,所以可以归结为

t=A[i]+B[i]+t;t初始化为0。

        我们算出t之后,t可能>=10,这时候我们只需要个位,然后进1,所以C[i]=t%10;

        如果算出是否有进位呢?只需要用t/10判断,因为t<10的时候,t=0;

        算法如下:      

#include <iostream>
#include <vector>
using namespace std;

vector<int> add(vector<int> &A,vector<int> &B){
	if(A.size()<B.size())return add(B,A);//大的数作为第一个参数 
	int t=0;
	vector<int> C;
	for(int i=0;i<A.size();i++){
		t+=A[i];//t=A[i]+B[i]+t
		if(i<B.size())t+=B[i];
		C.push_back(t%10);
		t/=10;
	}
	if(t)C.push_back(t); //如果t==1,说明有进位,因为是逆序,在结尾进位即可
	return C;
} 

int main(){
	string a,b;//用字符串存,因为长度太长long long 存储不了
	vector<int> 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');
	//计算
	vector<int> C=add(A,B);
	//返回
	for(int i=C.size()-1;i>=0;i--){
	cout << C[i];
	}
	return 0; 
}

5、高精度减法

        这里不考虑-10-10等这些负数情况,只考虑正数

      高精度减法,我们要考虑到(进1)的情况,则也需要一个t来记录是否需要进1,与高精度加法思路相同,t=A[i]-B[i]-t;但是需要注意的是这里的t可能存在<0和>=0的情况,因为我们这里无法通过代码来通俗的描述进1变十的情况,那么就只能直接A[i]-t-B[i],那么必定会出现负数情况,那该如何存储到C数组中呢,只需要对(t+10)%10,存储即可,可以进行手算验证,这里的t+10呢是防止出现负数情况,如果是正数呢,t+10然后再模10其实就回去了,没有变。如t=3,13%10=3,如果是t=-2,存入的数就为8,这里因为借了十,就加10,也可以这样理解。

        那么这里t<0呢,就代表其实是需要进位的,所以就可以写t<0时,t=1;则会t=0;

        当然,这个后续需要去掉前导0,因为在运算时候可能位数改变如

        代码如下:

#include <iostream>
#include <vector>
using namespace std;


bool cmp(vector<int> &A,vector<int> &B){//比较A和B谁大 
    if(A.size()!=B.size())return A.size()>B.size();
    for(int i=A.size()-1;i>=0;i--){
        if(A[i]!=B[i])return A[i]>B[i];
    }
    return true;
}

vector<int> sub(vector<int> &A,vector<int> &B){
    if(!cmp(A,B))cout << '-';
    if(!cmp(A,B))return sub(B,A);//如果A不大于B,则转一下
    vector<int> C;
    for(int i=0,t=0;i<A.size();i++){
        t=A[i]-t;
        if(i<B.size())t-=B[i];
        C.push_back((t+10)%10);
        if(t<0)t=1;
        else t=0;
    }
    while(C.size()>1 && C.back()==0)C.pop_back();
    return C;
}



int main(){
    string a,b;
    vector<int> 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');
    vector<int> C;
    C=sub(A,B);
    for(int i=C.size()-1;i>=0;i--){
        cout << C[i];
    }
    return 0;
    
}

6、高精度乘法

这里我们只考虑大数 X 小数的情况(A[i]xb),也就是b用int存储,在大多场合已经够用了

       在高精度乘法中,我们可以把乘数看做一个整体依次相乘被乘数,被除也需要用t标记进位,因为当相乘后需要进行逐次相加,则相加后,我们可以取除了余数的前几项的进位,然后用在下次计算中把t再次加起来。而计算结束的时候也就是没有进位的时候。        

        设C=(A[i]*b+t)%10;//运算后取模,这里需要把进位也加上去

        且t=(t+A[i]*b)/10;//运算后取除最后一项的前几项且加上进位并存储到t变量,为下一次做准备。

、例如:

代码:

#include<iostream>
#include<vector> 
using namespace std;


//C = A * b
vector<int> mul(vector<int> &A,int b){
	vector<int> C;
	int t=0;//进位 
	for(int i=0;i<A.size() || t;i++){//当进位没有处理完就继续 
		if(i<A.size())t+=A[i]*b;//当A[i]没有扫完
		C.push_back(t%10);
		t/=10;
	}
	while(C.size()>1 && C.back()==0)C.pop_back();//当b是0时 可能出现多个0,这时候弹出 
	return C;
}


int main(){
	string 	a;
	int b;
	vector<int> A;
	cin >> a >> b;
	for(int i=a.size()-1;i>=0;i--)A.push_back(a[i]-'0');
	vector<int> C=mul(A,b);
	for(int i=C.size()-1;i>=0;i--)cout << C[i];
	return 0;
}
 

7、高精度除法

注意:除法区别于加法、减法、乘法,除法是从高位计算,这里也是用高精度x低精度

        因为除法比较特殊,没有所谓什么进位什么的,因为只会越来越小,除了需要处理前导0。这里只需要一个r变量存储计算过程中的余数就能轻松写出除法代码,因为计算机总是一个数字一个数字的进行扫描,第一位不能商的情况下会商一个0,每次求出r余数的时候,因为在数字没有扫描完全部的时候,都可以进行求商(包括0),程序执行时这样的,

        则r=r*10+A[i];

           c=r/b//将商存入商数组。

           r=r%b;//求每一步的余数

        例如:

  代码:

#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;

vector<int> div(vector<int> &A,int &b,int &r){
	vector<int> C;
	r=0;
	for(int i=A.size()-1;i>=0;i--){//高位开始,区别于加减乘 
		r=r*10+A[i];
		C.push_back(r/b);
		r%=b;
	}
	reverse(C.begin(),C.end());//注意:算出的结果也是正序的,这里翻转是因为需要去掉前导0.且与加减乘相对应; 
	while(C.size()>1 && C.back()==0 )C.pop_back();
	return C; 
}


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

  • 23
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
高精度加法是一种应用广泛的算法,用于对两个大数进行求和。以下是高精度加法的实现步骤: 1. 将两个大数分别存储在两个数组中,注意数组的长度需要根据两个大数的位数来确定。 2. 从低位到高位依次将两个数组中对应位置的数相加,同时考虑进位。 3. 将相加后的结果存储在一个新的数组中,并将进位的值累加到后面的数位中。 4. 最后得到的结果可能会有多余的前导零,需要将其去掉。 以下是一个C++实现的高精度加法函数: ```cpp #include <iostream> #include <cstring> using namespace std; const int MAXN = 10010; int main() { char a[MAXN], b[MAXN], c[MAXN]; memset(a, 0, sizeof(a)); memset(b, 0, sizeof(b)); memset(c, 0, sizeof(c)); cin >> a >> b; int lena = strlen(a), lenb = strlen(b); int len = max(lena, lenb), carry = 0; for(int i = 0; i < len; i++) { int x = i < lena ? a[lena - i - 1] - '0' : 0; int y = i < lenb ? b[lenb - i - 1] - '0' : 0; int sum = x + y + carry; c[i] = sum % 10 + '0'; carry = sum / 10; } if(carry) c[len++] = carry + '0'; while(len > 1 && c[len - 1] == '0') len--; for(int i = len - 1; i >= 0; i--) cout << c[i]; return 0; } ``` 在上面的代码中,我们首先定义了三个数组a、b和c,分别用于存储两个大数和它们的和。然后使用strlen函数求出两个大数的长度,再使用一个变量carry来记录进位的值。接下来使用一个循环从低位到高位依次将两个大数中对应位置的数相加,同时考虑进位。最后得到的结果可能会有多余的前导零,需要将其去掉,然后将c数组中的数倒序输出即可。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

努力奋斗的张同学

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值