HDU 1753 大明A+B(大数加法,数组模拟)

来源:互联网 发布:知乎上面的神回复 编辑:程序博客网 时间:2024/05/01 08:32

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1753

Problem Description
话说,经过了漫长的一个多月,小明已经成长了许多,所以他改了一个名字叫“大明”。
这时他已经不是那个只会做100以内加法的那个“小明”了,现在他甚至会任意长度的正小数的加法。

现在,给你两个正的小数A和B,你的任务是代表大明计算出A+B的值。
 

Input
本题目包含多组测试数据,请处理到文件结束。
每一组测试数据在一行里面包含两个长度不大于400的正小数A和B。
 

Output
请在一行里面输出输出A+B的值,请输出最简形式。详细要求请见Sample Output。
 

Sample Input
1.1 2.91.1111111111 2.34443233431 1.1
 

Sample Output
43.45554344542.1


大数加法,需要处理多个细节问题,长度不超过400,就算用long long也存不了因此只能用数组来模拟,开一个长度为401的字符型数组(因为还要输入小数点符号),就可以解决输入的问题。对于每个数(a,b)分别再开两个数组分别保存整数部分和小数部分,处理输入的字符串得到整数部分时要注意必须要去掉前导0,有前导0的话会导致后面的加法错误(因此WA了3次T_T),分别做小数和整数的加法,每个数大于等于10的话前一位进1,最后输出同样要注意要去掉后导0

AC代码如下:

#include<iostream>#include<string>using namespace std;char a[401],b[401];bool search(char a[401]){//是否有小数点int len=strlen(a),i;for(i=0;i<len;i++)if(a[i]=='.')return true;if(i>=len)return false;return false;}int main(){//freopen("E:\\in.txt","r",stdin);//freopen("E:\\in_test.txt","w",stdout);int ca[401],cb[401],tempa[401],tempb[401];while(~scanf("%s %s",&a,&b)){//输入两个数intib=0,tb=0,cntb=0,i=0,t=0,cnt=0,j,len=0;//重置计数标志int res[401]={0},re[401]={0},ins=0,in=0;bool flag=false,flags=true,flagn=false;memset(tempa,0,sizeof(tempa));//重置memset(tempb,0,sizeof(tempb));memset(ca,0,sizeof(ca));memset(cb,0,sizeof(cb));if(search(a)){while(a[i]!='.'){i++;len++;}for(j=0;a[j]!='.';j++)//忽略前导0if(a[j]!='0') break;if(j>=len) tempa[t++]=0;//如果小数点前面全部是0,则给a整数数组赋值0else{i=j;while(a[i]!='.'){//a整数部分tempa[t++]=a[i]-'0';i++;}}while(a[i++]){//a小数部分ca[cnt]=a[i]-'0';cnt++;}cnt--;}else{while(a[i]){//无小数点,直接复制到tempatempa[t++]=a[i]-'0';i++;}}len=0;//重置长度以计算b的长度if(search(b)){while(b[ib]!='.'){len++;ib++;}for(j=0;b[j]!='.';j++)//忽略前导0if(b[j]!='0') break;if(j>=len) tempb[tb++]=0;else{ib=j;while(b[ib]!='.'){//b整数部分tempb[tb++]=b[ib]-'0';ib++;}}while(b[ib++]){//b小数部分cb[cntb]=b[ib]-'0';cntb++;}cntb--;}else{while(b[ib]){//无小数点,直接复制到tempbtempb[tb++]=b[ib]-'0';ib++;}}if(search(a)||search(b)){//a或b为小数则进行小数的加法运算int temp=cnt>cntb?cnt:cntb;for(i=0;i<temp;i++){if(i>=cnt) re[in++]=cb[i];else if(i>=cntb) re[in++]=ca[i];else re[in++]=ca[i]+cb[i];//小数部分求和}for(i=in-1;i>0;i--){//处理大于10的部分,注意,这里不对re[0]进行处理if(re[i]>9){re[i]-=10;re[i-1]++;}}if(re[0]>9){//判断第一位小数相加后是否大于10re[0]-=10;flag=true;}}for(i=t-1,ib=tb-1;i>=0||ib>=0;i--,ib--){//计算整数部分的和if(ib<0) res[ins++]=tempa[i];else if(i<0) res[ins++]=tempb[ib];else res[ins++]=tempa[i]+tempb[ib];}if(flag)res[0]+=1; for(i=0;i<ins-1;i++){//转化结果中大于10的部分 这里不对res[ins-1]进行处理if(res[i]>9){res[i]-=10;res[i+1]++;}}if(res[ins-1]>9){res[ins-1]-=10;flagn=true;}for(i=0;i<in;i++)//判断小数是否全为0以决定是否输出小数点if(re[i]!=0)break;if(i>=in) flags=false;if(flagn)cout<<"1";for(i=ins-1;i>=0;i--)//输出整数部分cout<<res[i];if((search(a)||search(b))&&flags){//存在小数,且小数部分不全为0cout<<".";for(i=0;i<in;i++){//输出小数部分for(t=i;t<in;t++)//忽略小数的后导0if(re[t]!=0)break;if(t>=in)break;cout<<re[i];}}cout<<endl;}return 0;}


另外,附上测试用的数据以及输出结果

输入:

1.1 2.91.1111111111 2.344432334341 1.121.3423 2.1342323432.32 1232222 23219.2 12.119.2 12.92013.2013 3029.302999.9 99.90.99 99.999.9 0.199.99 009.1100098.8 3.321.2 1.90.1 0.91.0 0.101.0001 0010.00100

输出:

43.455543445442.123.4765324664.3245431.332.15042.5042199.8100.89100109.1102.123.111.111.0011


1 0
原创粉丝点击