您的位置:首页 > 其它

HDOJ 1753 大明A+B

2014-07-31 17:13 246 查看

http://acm.hdu.edu.cn/showproblem.php?pid=1753

大明A+B

Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)

Total Submission(s): 8296    Accepted Submission(s): 2929


[align=left]Problem Description[/align]
话说,经过了漫长的一个多月,小明已经成长了许多,所以他改了一个名字叫“大明”。

这时他已经不是那个只会做100以内加法的那个“小明”了,现在他甚至会任意长度的正小数的加法。

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

 

[align=left]Input[/align]
本题目包含多组测试数据,请处理到文件结束。

每一组测试数据在一行里面包含两个长度不大于400的正小数A和B。
 

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

 

[align=left]Sample Input[/align]

1.1 2.9
1.1111111111 2.3444323343
1 1.1

 

[align=left]Sample Output[/align]

4
3.4555434454
2.1

 
思路清晰,算法只用到了大数,但里边需要注意的地方很多

先计算小数位的和,因为十分位可能向各位进位,进位时a[0]+=1就行,然后后边直接用;

然后计算整数位的和,也就是大数相加,只是应该注意把字符串中的数存到a[]时,要写成a[j]+=s1[i]-'0',因为要考虑进位

代码后边附几组数据,这些过了应该就可以AC
/*思路清晰,算法只用到了大数,但里边需要注意的地方很多
先计算小数位的和,因为十分位可能向各位进位,进位时a[0]+=1就行,然后后边直接用;
然后计算整数位的和,也就是大数相加,只是应该注意把字符串中的数存到a[]时,要写成a[j]+=s1[i]-'0',因为要考虑进位
*/
#include<stdio.h>
#include<string.h>
#define MAX 450
int main()
{
int a[MAX],b[MAX],num_1[MAX],num_2[MAX],i,j,k,n;
char s1[MAX],s2[MAX];
while(~scanf("%s %s",s1,s2))
{
memset(num_1,0,sizeof(num_1));
memset(num_2,0,sizeof(num_2));
memset(a,0,sizeof(a));
memset(b,0,sizeof(b));
n=strlen(s1);
for(i=0;i<n;i++)//s1[i]为小数点
if(s1[i]=='.') break;
for(k=0,j=n-1;j>i;j--,k++)//s1有k位小数
num_1[k]=s1[j]-'0';
int i_1=i,k_1=k,n_1=n;

n=strlen(s2);
for(i=0;i<n;i++)//s2[i]为小数点
if(s2[i]=='.') break;
for(k=0,j=n-1;j>i;j--,k++)//s2有k位小数
num_2[k]=s2[j]-'0';
int i_2=i,k_2=k,n_2=n;
if(k_1>=k_2)//小数相加,注意十分位进位的情况  //分两这情况(k_1>=k_2)和(k_1<k_2)是因为不确定哪个小数点后的位数大
{//如果k_1>=k_2,把计算的结果放到num_1[]中
for(i=k_1-k_2,j=0;i<k_1;i++,j++)
{
num_1[i]+=num_2[j];
if(num_1[i]>=10)
{
num_1[i]-=10;
num_1[i+1]+=1;
}
//printf("%d#\n",num_1[i]);
}
if(num_1[i]==1)//十分位进到个位
{
num_1[i]-=1;
a[0]+=1;
}
}
else if(k_2>k_1)//如果k_2>k_1,把计算的结果放到num_2中。
{
for(i=k_2-k_1,j=0;i<k_2;i++,j++)
{
num_2[i]+=num_1[j];
if(num_2[i]>=10)
{
num_2[i]-=10;
num_2[i+1]+=1;
}

}
if(num_2[i]==1)//十分位进到个位
{
num_2[i]-=1;
a[0]+=1;
}
}
//上边小数位相加分两种情况,下边小数位的输出也分两种情况

for(j=0,i=i_1-1;i>=0;i--,j++)//这里是a[j]+=s1[i]-'0',因为考虑到小数会给a[0]进位。
a[j]+=s1[i]-'0';            //这里其实只给a[0]+=s1[o]-'0',其余还是a[j]=s1[i]-'0',只是这样写和把a[0]独分出来效果一样,就这样写了
for(j=0,i=i_2-1;i>=0;i--,j++)//给b[0]赋值时和a[]一样
b[j]=s2[i]-'0';
for(i=0;i<MAX;i++)//计算整数部分,存到a[]中
{
a[i]+=b[i];
if(a[i]>=10)
{
a[i]-=10;
a[i+1]+=1;
}
}
for(i=MAX-1;i>0;i--)//输出整数部分
if(a[i]!=0) break;
for(;i>=0;i--)
printf("%d",a[i]);

if(k_1>=k_2)//输出小数部分
{
for(i=k_1-1;i>=0;i--)//这里的for循环是判断小数点后是否有值,如果没有值,循环进行到底,最后i是-1
if(num_1[i]!=0) break;//如果i==-1,则不执行下边if(i!=-1),也就是不输出小数点和小数点后边的0
for(j=0;j<k_1;j++)//这个for循环的作用是不输出计算得到的小数后边的0,如1.028+1.072。在for之前结果是2.100,执行完for就把 后边的0去掉,结果为2.1
if(num_1[j]!=0) break;
if(i!=-1)//如果小数点后边有值,输出小数点和后边的数
{
printf(".");
for(i=k_1-1;i>=j;i--)
printf("%d",num_1[i]);
}
}
else if(k_1<k_2)//这里的if和上边一样
{
for(i=k_2-1;i>=0;i--)
if(num_2[i]!=0) break;
for(j=0;j<k_2;j++)
if(num_2[j]!=0) break;
if(i!=-1)
{
printf(".");
for(i=k_2-1;i>=j;i--)
printf("%d",num_2[i]);
}
}
printf("\n");

}
return 0;
}
/*
0 0
1.2333 1.2667
99999 1
12121213213124342545354545 13312312321312321321.02300000000000000000000000000
1.0001 1.00002
99999.889 0.111
1000.0 10000.0
112233.1 333.9
123450000 777
123400000 777.700
0.000 0.0000
1212121212.1111111 21212121.33300000000000000
*/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: