首页 > 其他 > 详细

HDOJ 1753 大明A+B

时间:2014-07-31 21:02:57      阅读:353      评论:0      收藏:0      [点我收藏+]


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


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

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


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


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


Sample Input
1.1 2.9 1.1111111111 2.3444323343 1 1.1
 


Sample Output
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
*/



HDOJ 1753 大明A+B,布布扣,bubuko.com

HDOJ 1753 大明A+B

原文:http://blog.csdn.net/simoncoder/article/details/38320541

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!