51nod题解 1005 大数加法

51nod 1005 大数加法

前言:不知不觉就已经快要大三了,意识到自身的专业水平还有很大的不足,也该收收心把心思放在学习上了.这是我刷的第一道题,也是我第一次写博客,想通过记录博客的形式记录下自己学习的过程,并督促自己.我的代码还存在很多的问题,我的博客也写的很差,我相信会逐渐好起来的.

题目

题目

我的代码

在这里插入图片描述

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

int main() 
{
	string A,B;
	cin>>A>>B;
	if(A.size()<=10001||B.size()<=10001)		//由于可能存在'-',所以限制字符串A,B的长度小于10001, 
	{	
		
		if(A[0]!='-'&&B[0]!='-')				//情况一:当A,B都为正数的时候 
		{ 
			reverse(A.begin(),A.end());			//反转函数,将A,B反转过来,便于机器进行运算 
			reverse(B.begin(),B.end());			
			int n=max(A.size(),B.size());		//最大值函数,取A,B的长度最大值为n 
			string C(n+1,0);					//字符串C用于输出 ,同时多给一位用于进位,且设置每一位为0用于计算 
			for(int i=0;i<n;i++)
			{
				int av=0;						//av为当前A的值,当i大于 A的长度时为0 
				if(i<A.size())
				{av=A[i]-'0';}					//字符串中的数是由ASCII码表示,要减去'0'的ASCII码,在数值上才表示实际数大小 
				int bv=0;						
				if(i<B.size())
				{bv=B[i]-'0';}
				int sum=C[i]+av+bv;				//sum用于储存总和,C[i]表示上一位运算中可能存在进位 
				C[i]=sum%10;					//总和的余数为该位的值 
				C[i+1]=sum/10;					//总和的商为下一位的进位 
			}
			if(C[n])							//一开始字符串C就多给了一位,用以进位,如果该位有进位则输出,没进位则不输出 
			{
				cout<<char(C[n]+'0');
			}
			for(int k=n-1;k>=0;k--)				//将剩下字符串反向输出得到两数相加的和,要注意每一位要加上'0',转化为相应的ASCII码 
			{
				cout<<char(C[k]+'0');
			}
		}
		
		if(A[0]=='-'&&B[0]=='-')				//情况二:当A,B都为负的时候 ,相当于A,B绝对值相加的值的相反数 
		{ 
			A.erase(0,1);						//删除负号 
			B.erase(0,1);						//删除负号 
			reverse(A.begin(),A.end());			
			reverse(B.begin(),B.end());
			int n=max(A.size(),B.size());		
			string C(n+1,0);					
			for(int i=0;i<n;i++)
			{
				int av=0;
				if(i<A.size())
				{av=A[i]-'0';}
				int bv=0;
				if(i<B.size())
				{bv=B[i]-'0';}
				int sum=C[i]+av+bv;
				C[i]=sum%10;
				C[i+1]=sum/10;
			}
			cout<<'-';							//输出负号 
			if(C[n])
			{
				cout<<char(C[n]+'0');
			}
			for(int k=n-1;k>=0;k--)
			{
				cout<<char(C[k]+'0');
			}
		}
		
		if(A[0]=='-'&&B[0]!='-')				//情况三:当A为负数,B为正数的时候 
		{ 
			int flag=0,blag=1; 					//flag为借位标志位,blag符号标志位 
			A.erase(0,1);						//删除A前面的负号 
			if(A.size()<B.size())				//当A的长度小于B的长度 
			{
				blag=0;							//由于正数大于负数,符号标志位为0,不输出负号 
				A.swap(B);						//swap交换函数,将A和B交换,使位数长的字符串在前 
			 } 
			if(A.size()==B.size())				//当A的长度等于B的长度 
			{
				if(B>A)							//比较A,B字符串的大小,当B大于A时,即正数大于负数时,string字符串比较运算符的比较规则是从低位到高位按ASCII码进行比较 
				{
					B.swap(A);					//将B和A交换 ,将大的数放在前面 
					blag=0;						//正数大于负数,不输出负号 
				}
			 } 
			reverse(A.begin(),A.end());			
			reverse(B.begin(),B.end());
			int n=max(A.size(),B.size());
			string C(n+1,0);
			for(int i=0;i<n;i++)
			{
				int av=0;
				if(i<A.size())
				{av=A[i]-'0';}
				int bv=0;
				if(i<B.size())
				{bv=B[i]-'0';}
				int sub=av-bv;					//sub为A当前值减B当前值 
				if(sub<0)						//如果sub为负数,既需要借位 
				{
					sub+=10;					//借位后,sub+10 
				}
				C[i]=sub-flag; 					//输出字符串C的当前位为sub-上一位的借位 
				if(C[i]<0)						//sub-借位小于0,既当sub=0,上一位有借位时,需要向上借位 
				{
					C[i]+=10;					//借位后当前值+10 
					flag=1; 					//向上借位,flag=1 
					continue;					//退出本次循环 
				} 
				if(av-bv<0)						//如果A当前值减B当前值小于0 
				{
					flag=1;						//则需要向上借位,flag=1 
				} 
				else
				{
					flag=0;						//不需要向上借位,flag=0 
				}
			}
			if(blag)							//如果标志符号位为1,输出负号 
			{
			cout<<'-';
			}
			if(C[n])							//进位位,理论上该种情况下可删除			
			{
				cout<<char(C[n]+'0');
			}
			int cflag=1; 						//0标志位,用于第一个有意义的数前面是否存在0的检查 
			for(int k=n-1;k>=0;k--)
			{
				if(cflag)
				{
					if(C[k]==0)					//如果C当前位为0,跳过该位 
					{
					continue; 
					}
					else						//如果检查到当前位不为0,则表示该位为第一位有意义的位,取消检查,进行输出 
					{
					cflag=0;					//取消检查 
					} 
				}
				cout<<char(C[k]+'0');			//输出结果 
			}
		}
		
		if(A[0]!='-'&&B[0]=='-')				//情况四:与A为负,B为正情况同理 
		{ 
			int flag=0,blag=0; 
			B.erase(0,1);
			if(A.size()<B.size())				//负数大于正数 
			{
				blag=1;							//输出负号 
				A.swap(B);						//负数在前 
			} 
			if(A.size()==B.size())				//位数相同 
			{
				if(B>A)							//负数大于正数 
				{
					B.swap(A);					//负数在前 
					blag=1;						//输出负号 
				}
			} 
			reverse(A.begin(),A.end());
			reverse(B.begin(),B.end());
			int n=max(A.size(),B.size());
			string C(n+1,0);
			for(int i=0;i<n;i++)
			{
				int av=0;
				if(i<A.size())
				{av=A[i]-'0';}
				int bv=0;
				if(i<B.size())
				{bv=B[i]-'0';}
				int sub=av-bv;
				if(sub<0)
				{
					sub+=10;
				}
				C[i]=sub-flag; 
				if(C[i]<0)
				{
					C[i]+=10;
					flag=1; 
					continue;
				} 
				if(av-bv<0)
				{
					flag=1;
				} 
				else
				{
					flag=0;
				}
			}
			if(blag)							
			{
			cout<<'-';
			}
			if(C[n])
			{
				cout<<char(C[n]+'0');
			}
			int cflag=1;
			for(int k=n-1;k>=0;k--)
			{
					if(cflag)
				{
					if(C[k]==0)
					{
					continue; 
					}
					else
					{
					cflag=0;
					} 
				}
				cout<<char(C[k]+'0');
			}
		}	
	}
	
	cout<<endl;
	return 0; 
}

总结

大数加法的实现并不难,难是难在数可能为负数,这其实就相当于大数加法和大数减法的混合,多出了很多情况,会负责很多,我的解题思路很简单粗暴,代码也很长,重复的部分很多,实在很糟糕,我相信经过不断的训练之后,会写出更好的解法.

知识点

#include< algorithm >algorithm意为"算法",是C++的标准模版库(STL)中最重要的头文件之一
swap (A,B)algorithm头文件中定义的交换函数, 可以交换存储在两个对象中的值。
reverse(first,last)algorithm头文件中定义的反转函数,用于反转在[first,last)范围内的顺序
max(A,B)algorithm头文件中定义的最大值函数,A,B可以为整型或浮点型,返回值为A,B中的最大值
#include< string >string是C++系统提供的一个类,封装了常用的字符串操作.使用string类型,我们必须包含头文件 < string >。
begin()string头文件中定义的 begin()函数返回一个迭代器,指向字符串的第一个元素.
end()string头文件中定义的end()函数返回一个迭代器,指向字符串的末尾(最后一个字符的下一个位置).
比较运算符(<,=,>)用于string类型的比较运算符,比较规则按从最低位到最高位的ASCII码进行比较
size()string头文件中定义的size(),用于string类型,返回string的长度,等同于length()
erase(A,B)string头文件中定义的erase(),可以用来删除字符串中的字符,从位置A开始,删除长度B个字符
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值