栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

高精度加减法的应用——试解大数之和

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

高精度加减法的应用——试解大数之和

一、前言

        我是夏日弥,很高兴看到您来读我的博客,

        这一次小夏将为您讲解一道经典的算法竞赛入门题,使用的方法涉及高精度加法和减法,vector动态数组,这是一种比较容易想得到,却不好代码实现的方法。

        于此同时,我会为您提供另一种代码比较简洁,却不是很好理解的方法——消零法;

        时间有限,本次讲解会比较简洁,还请您包容和理解,让我们正式开始吧!

二、大数之和

        2.1、题目:

大数之和:      

给定一些大整数,请计算其和。

输入格式:

测试数据有多组。对于每组测试数,首先输入一个整数n(n≤100),接着输入n个大整数(位数不超过200)。若n=0则表示输入结束。

输出格式:

对于每组测试,输出n个整数之和,每个结果单独占一行。

输入样例:
2
43242342342342
-1234567654321
0

输出样例:
42007774688021
         2.2、高精度加减法模拟:
#include
using namespace std;

const int N =100010;

vector add(vector& A,vector& B)
{
	vector C;
	
	int t = 0;
	for(int i =0;i &A,vector &B)
{	cout<<"cmp函数已执行"<= 0;i--)cout<= 0;i--)cout< B.size();//长度不一样时可以直接判断,返回A.size() > B.size()的真假; 
	for(int i = A.size()-1; i >= 0;i--) //末尾往前依次判断; 
		if(A[i] != B[i])return A[i] > B [i];//例如987和986比较,从末尾7和6比,直接返回7>6为真,即a>b为真; 
	return true; //如果两数相等,返回为真; 
}

vector sub(vector &A,vector &B)//该函数必须确保A>=B; 
{
	vector C;//定义答案数组C; 
	for(int i = 0,t = 0; i0,说明没有借位; 
	}
	
	while(C.size() > 1 && C.back() == 0)C.pop_back();//头部消零,C.size()>1 确保了C里面不是一位数,如果 C 是0的话是不用消去的;
	 
	
	return C;
}//高精度减法函数,返回值为vector数组类型; 


vector trans(string a){
	vector C;
	for(int i=a.size()-1;i>=0;i--)C.push_back(a[i]-'0');
	return C;
}



int main(){
	int n;
	
	while(cin>>n && n!=0 ){
		
	vector ans={0};//每一次都定义新的ans; 
	bool ans_bool = 1;//新的ans_bool的状态为 正; 
	bool a_bool = 1;//新的a_bool的状态为 正; 
	
		for(int j = 0; j>a;//输入部分; 
		
		vector A ;
		
		if(a[0] == '-'){
			a_bool = 0;//如果是负数,更新a_bool为负数;
			
			for(int i = a.size()-1;i>0;i--)A.push_back(a[i]-'0');
		}
		else{
		a_bool = 1;//如果是正数,更新a_bool为正数;
		A = trans(a);//取a的绝对值; 
		}
		
		//取值部分&判断部分; 
		
		
		cout<<"这里将输出ans_bool 和a_bool 的值,分别是 "ans; 
		
		//比较部分:ans和A到底谁大?
		
		}
		cout<=0;i--)cout<=0;i--)cout<

        我们拆成几个小问题来逐一破解:

        1,实现高精度加法模板:

vector add(vector& A,vector& B)
{
	vector C;//定义答案数组; 
	
	int t = 0;//定义临时变量t,储存位数的加法结果,如123+29中的3 + 9 = 12;t = 12;  
	for(int i =0;i 10,t/=10, t = 1;  
	}
	if(t)C.push_back(1);//特判:如果t = 1,也就是最高位进位,直接压入C的最后一位,如999 + 1 = 000,此时t = 1,压入1使其变为 1000; 
	return C; 
	
}//高精度加法;

        2、实现高精度减法模板:

bool cmp(vector &A,vector &B)
{	cout<<"cmp函数已执行"<= 0;i--)cout<= 0;i--)cout< B.size();//长度不一样时可以直接判断,返回A.size() > B.size()的真假; 
	for(int i = A.size()-1; i >= 0;i--) //末尾往前依次判断; 
		if(A[i] != B[i])return A[i] > B [i];//例如987和986比较,从末尾7和6比,直接返回7>6为真,即a>b为真; 
	return true; //如果两数相等,返回为真; 
}

vector sub(vector &A,vector &B)//该函数必须确保A>=B; 
{
	vector C;//定义答案数组C; 
	for(int i = 0,t = 0; i0,说明没有借位; 
	}
	
	while(C.size() > 1 && C.back() == 0)C.pop_back();//头部消零,C.size()>1 确保了C里面不是一位数,如果 C 是0的话是不用消去的;
	 
	
	return C;
}//高精度减法函数,返回值为vector数组类型;

        高精度减法比较复杂,因为要判定负数的情况,

        我们写的这个模板仅仅限于A >= B 的情况;

        负数其实应该是一个...在输入输出被考虑的部分:

        我们的加减法本质是 先根据加数的正负计算它们绝对值的和或差

        再判断 结果的正负

        比如说我们计算 1 - 99 = ?

        我们实际上把它变成了 99 - 1 = 98;

        再判定 1 为正数, -99 为负数 ,1 的绝对值比 99的绝对值要大,所以取负号;

         变成 -98;

         3、将string转变成vector

        

vector trans(string a){
	vector C;
	for(int i=a.size()-1;i>=0;i--)C.push_back(a[i]-'0');
	return C;
}

        倒序转换,没什么可说的,值得注意的就是 a[i] 是 char型,这里我们采取

        a[i] - '0' 的方式转变成 int 类型 如: '9' - '0' = 9;

        4、处理输入输出部分:

#include
using namespace std;
int main(){
	int n;
	while(cin>>n && n!=0){
		
	}//多组输入,直到输入0结束; 
}

        最轻松的部分

        5、正负号 以及 绝对值大小判定:

        小夏的做法是先判定绝对值大小,再判定正负号:

        

int main(){
	int n;
	
	while(cin>>n && n!=0 ){
		
	vector ans={0};//每一次都定义新的ans; 
	bool ans_bool = 1;//新的ans_bool的状态为 正; 
	bool a_bool = 1;//新的a_bool的状态为 正; 
	
		for(int j = 0; j>a;//输入部分; 
		
		vector A ;
		
		if(a[0] == '-'){
			a_bool = 0;//如果是负数,更新a_bool为负数;
			
			for(int i = a.size()-1;i>0;i--)A.push_back(a[i]-'0');
		}
		else{
		a_bool = 1;//如果是正数,更新a_bool为正数;
		A = trans(a);//取a的绝对值; 
		}
		
		//取值部分&判断部分; 
		
		
		cout<<"这里将输出ans_bool 和a_bool 的值,分别是 "ans; 
		
		//比较部分:ans和A到底谁大?
		
		}
		cout<=0;i--)cout<=0;i--)cout<

        小夏为您注释了所有的8种情况;

        小夏使用的是 ans_bool 和 a_bool 来分别判断 ans 和 a 的正负:1 为正 , 0 为负;

        6、连接所有模板

        缝合怪,启动!

        连接上面的所有模板,再删除注释,最终的程序如下:

        最终代码
#include
using namespace std;

const int N =100010;

vector add(vector& A,vector& B)
{
	vector C;
	
	int t = 0;
	for(int i =0;i &A,vector &B)
{	
	if(A.size() != B.size()) return A.size() > B.size();//长度不一样时可以直接判断,返回A.size() > B.size()的真假; 
	for(int i = A.size()-1; i >= 0;i--) //末尾往前依次判断; 
		if(A[i] != B[i])return A[i] > B [i];//例如987和986比较,从末尾7和6比,直接返回7>6为真,即a>b为真; 
	return true; //如果两数相等,返回为真; 
}

vector sub(vector &A,vector &B)//该函数必须确保A>=B; 
{
	vector C;//定义答案数组C; 
	for(int i = 0,t = 0; i0,说明没有借位; 
	}
	
	while(C.size() > 1 && C.back() == 0)C.pop_back();//头部消零,C.size()>1 确保了C里面不是一位数,如果 C 是0的话是不用消去的;
	 
	
	return C;
}//高精度减法函数,返回值为vector数组类型; 


vector trans(string a){
	vector C;
	for(int i=a.size()-1;i>=0;i--)C.push_back(a[i]-'0');
	return C;
}



int main(){
	int n;
	
	while(cin>>n && n!=0 ){
		
	vector ans={0};//每一次都定义新的ans; 
	bool ans_bool = 1;//新的ans_bool的状态为 正; 
	bool a_bool = 1;//新的a_bool的状态为 正; 
	
		for(int j = 0; j>a;//输入部分; 
		
		vector A ;
		
		if(a[0] == '-'){
			a_bool = 0;//如果是负数,更新a_bool为负数;
			
			for(int i = a.size()-1;i>0;i--)A.push_back(a[i]-'0');
		}
		else{
		a_bool = 1;//如果是正数,更新a_bool为正数;
		A = trans(a);//取a的绝对值; 
		}
		
		//取值部分&判断部分; 
		
		
		
		if(cmp(ans,A)){

			if(ans_bool && !a_bool){

				ans = sub(ans,A);
				ans_bool = 1; 
			}
			else if(ans_bool && a_bool){

				ans = add(ans , A);
				ans_bool = 1; 
			}
			else if(!ans_bool && a_bool){

				ans = sub(ans,A);
				ans_bool = 0;
			}
			else if(!ans_bool && !a_bool){
				ans = add(ans,A);
				ans_bool = 0;
			}
			
		}//这个部分是ans>A 
		else{
			if(ans_bool && !a_bool){

				ans = sub(A,ans);
				ans_bool = 0; 
			}
			else if(ans_bool && a_bool){

				ans = add(ans , A);
				ans_bool = 1; 
			}
			else if(!ans_bool && a_bool){

				ans = sub(A,ans);
				ans_bool = 1;
			}
			else if(!ans_bool && !a_bool){

				ans = add(ans,A);
				ans_bool = 0;
			}
			
		}//这个部分是A>ans; 
		
		//比较部分:ans和A到底谁大?
		
		}

		if(ans_bool){

		for(int i = ans.size()-1;i>=0;i--)cout<=0;i--)cout<

        2.3、消零法

        先加减再消去前导零:

        直接放上成果吧:

        值得注意的是部分编译器会提示数组越界,但小夏没查过是哪一部分越了界,懒狗

#include
using namespace std;
string sum(string a,string b)
{
    for(int i=201;i>=0;i--)
    {
        a[i]=a[i]+b[i]-'0';
        if(a[i]>'9'){
            a[i]-=10;
            a[i-1]++;
        }
    }
    return a;
}
string opp(string a){
    for(unsigned int i=0;i>n&&n!=0)
    {
        cin>>a;
        if(a[0]=='-')
        {
            a=a.substr(1);
            a=string(202-a.length(),'0')+a;
            a=opp(a);
        }
        else
        a=string(202-a.length(),'0')+a;
        for(int i=0;i>b;
            if(b[0]=='-')
        {
            b=b.substr(1);
            b=string(202-b.length(),'0')+b;
            b=opp(b);
        }
            else
        b=string(202-b.length(),'0')+b;
            a=sum(a,b);
        }
        if(a[0]=='9')
        {
            a=opp(a);
            cout<<"-";
        }
        int p=a.find_first_not_of('0');
    if(p==-1)
        cout<<"0"< 

三、尾声

        草草写的题解;

        还请您多加包涵;

     

                                                                                                                                    夏日弥死傲娇

                                                                                                                                        2021.12.2

我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号