原题:

Problem Description

I have a very simple problem for you. Given two integersA and B, your job is to calculate the Sum of A + B.

Input

The first line of the input contains an integerT(1<=T<=20) which means the number of test cases. Then T lines follow,each line consists of two positive integers, A and B. Notice that the integersare very large, that means you should not process them by using 32-bit integer.You may assume the length of each integer will not exceed 1000.

Output

For each test case, you should output two lines. Thefirst line is "Case #:", # means the number of the test case. Thesecond line is the an equation "A + B = Sum", Sum means the result ofA + B. Note there are some spaces int the equation. Output a blank line betweentwo test cases.

2

1 2

112233445566778899 998877665544332211

注意下面的输出格式要求:(说实话,你们老师要求这样写吗?

 )

Case 1:

1 + 2 = 3

 

Case 2:

112233445566778899 + 998877665544332211 =1111111111111111110

两行之间有空行,最后一行无空行,这个很简单,一个if或者for就可以解决。

下面进行分析。先声明,我只分析我认为的重点,并尽最大能力让跟我同水平及以下的朋友有所收获。至于你是否有更高的见解,欢迎你将它无偿的发表在下面面的留言板上。

分析:

首先这是一个加法问题。

其次,此题涉及到多组数据输入。

再次,本题明确说明这是一道大数据的题。

如果是简单的加法问题,我们可以这样:


[plain]     view plain     copy    
    
    print   ?    
1. #include<stdio.h>  
2. int main ()  
3. {  
4.     int a,b;  
5.     while(scanf("%d %d",&a,&b)!=EOF)  
6.           
7.         printf("a+b=%d",a+b);  
8.     return 0;  
9. }

#include<stdio.h>
int main ()
{
	int a,b;
	while(scanf("%d %d",&a,&b)!=EOF)
		
		printf("a+b=%d",a+b);
	return 0;
}

 

但是对于输入的数或者运算所得数超过了我们可以定义的数据类型,再用这种方法,就会出现一系列的错误。

度娘告诉你,这一类的问题有一个高大上的名字,叫做“高精度运算”。她还告诉你,遇到这种情况,你可以利用的数据类型有两种,一种是字符串,另一种是数组。http://baike.baidu.com/link?url=CpO17lLZr75a-a47YPC05dp7nfmeAQWEMimnTjDZ1oKmLZBfBFUDFscxRUz_nfSa

根据度娘的提示,我决定就采取她说的方法:用字符串读入数据,用数组存储数据。

这个又涉及到字符型和整型之间的转换,这一点在下面的代码中将有相应解释,看的时候注意点就是。

回想在你小学的时候,你学过一种东西叫做“竖式”,它的基本原理是:个位与个位对齐,十位与十位对齐,……;对齐的个位的上面加下面,如果得出的数超过十,就把超出的部分进给十位,没超出的留在原位上。在编程中,通过“/”和“%”的运算来实现。“/”得到进位的数,“%”得到留下的数。

本题的思路就是,利用数组的每个元素,储存大数据的各个位上的数。各个位上的数由上面的算法得到。

代码如下:


[plain]     view plain     copy    
    
    print   ?    
1. #include<stdio.h>  
2. #include<string.h>  
3. int main()  
4. {  
5.     chara[10001],b[10001];//将大数据分解成字符,作为一个数组输入  
6.     int a1[10001]={0},b1[10001]={0};//s[]作为两个大数据运算后的和,a1[],b1[]分别保存大数据转换为数字型后的各位数  
7.     int lena,lenb;//大数据的长度  
8.     int i,j,t;  
9.     int m;//与n搭配的计数单位  
10.     int n;//代表测试数据组数  
11.     int x;//代表Case :x   
12.     scanf("%d",&n);//输入测试组数  
13.     x=1;//为输出Case :x做准备  
14.     for(m=0;m<n;m++)//从第一组数据开始,每一组进行处理  
15.     {  
16.         int s[20002] ={0},k=0;//注意它们的位置  
17.         scanf("%s%s",a,b);//输入两个大数  
18.         printf("Case%d:\n", x);  
19.         printf("%s + %s = ", a, b);   
20.         lena=strlen(a);  
21.         lenb=strlen(b);//测量它们的长度  
22.         for(i=0;i<lena;i++)  
23.             a1[i]=a[i]-48;  
24.         for(j=0;j<lenb;j++)  
25.             b1[j]=b[j]-48;//0的ASCII码是48,这样做是把字符型转换为数字型,或者可以:b1[ ]=b1[ ]-'0';  
26.         while(i>=0&&j>=0)//倒着处理,最低位开始  
27.         {  
28.             s[k]=a1[i]+b1[j];//对位相加,先不进位  
29.             k++;  
30.             i--;  
31.             j--;  
32.         }  
33.         //对不齐的那些位,s[]等于a1[],b1[]中大于等于0的  
34.         if(i>=0)  
35.             while(i>=0)  
36.             {  
37.                 s[k]=a1[i];  
38.                 k++;  
39.                 i--;  
40.             }  
41.             else if(j>=0)  
42.                 while(j>=0)  
43.                 {  
44.                     s[k]=b1[j];  
45.                     k++;  
46.                     j--;  
47.                 }  
48.                 for(t=1;t<k;t++)//从个位到倒数第二最高位,进行进位处理  
49.                     if(s[t]>=10)  
50.                     {  
51.                         s[t]%=10;  
52.                         s[t+1]++;  
53.                     }  
54.                     if(s[k]!=0)//最高位如果不为零,就直接输出  
55.                         printf("%d",s[k]);  
56.                     for(t=k-1;t>0;t--)//从倒数第二高位起,开始输出。因为s[ ]是从个位开始加的,所以输出的时候,在形式上是逆序输出的。  
57.                         printf("%d",s[t]);  
58.                     printf("%c",'\n');//输完之后再加回车  
59.                     if(x!=n)printf("%c ",'\n'); //注意格式,非最后一组数据,后面有空行。   
60.                     x++;  
61.     }  
62.     return0;  
63. }


#include<stdio.h>
#include<string.h>
int main()
{
	chara[10001],b[10001];//将大数据分解成字符,作为一个数组输入
	int a1[10001]={0},b1[10001]={0};//s[]作为两个大数据运算后的和,a1[],b1[]分别保存大数据转换为数字型后的各位数
	int lena,lenb;//大数据的长度
	int i,j,t;
	int m;//与n搭配的计数单位
	int n;//代表测试数据组数
	int x;//代表Case :x 
	scanf("%d",&n);//输入测试组数
	x=1;//为输出Case :x做准备
	for(m=0;m<n;m++)//从第一组数据开始,每一组进行处理
	{
		int s[20002] ={0},k=0;//注意它们的位置
		scanf("%s%s",a,b);//输入两个大数
		printf("Case%d:\n", x);
		printf("%s + %s = ", a, b); 
		lena=strlen(a);
		lenb=strlen(b);//测量它们的长度
		for(i=0;i<lena;i++)
			a1[i]=a[i]-48;
		for(j=0;j<lenb;j++)
			b1[j]=b[j]-48;//0的ASCII码是48,这样做是把字符型转换为数字型,或者可以:b1[ ]=b1[ ]-'0';
		while(i>=0&&j>=0)//倒着处理,最低位开始
		{
			s[k]=a1[i]+b1[j];//对位相加,先不进位
			k++;
			i--;
			j--;
		}
		//对不齐的那些位,s[]等于a1[],b1[]中大于等于0的
		if(i>=0)
			while(i>=0)
			{
				s[k]=a1[i];
				k++;
				i--;
			}
			else if(j>=0)
				while(j>=0)
				{
					s[k]=b1[j];
					k++;
					j--;
				}
				for(t=1;t<k;t++)//从个位到倒数第二最高位,进行进位处理
					if(s[t]>=10)
					{
						s[t]%=10;
						s[t+1]++;
					}
					if(s[k]!=0)//最高位如果不为零,就直接输出
						printf("%d",s[k]);
					for(t=k-1;t>0;t--)//从倒数第二高位起,开始输出。因为s[ ]是从个位开始加的,所以输出的时候,在形式上是逆序输出的。
						printf("%d",s[t]);
					printf("%c",'\n');//输完之后再加回车
					if(x!=n)printf("%c ",'\n'); //注意格式,非最后一组数据,后面有空行。 
					x++;
	}
	return0;
}


 

我的错误:

1.出现几组加和累加的现象。

2.Case x:这里的x显示异常。

出错原因:

1.由于是多组数据输入,需要刷新的数据初始化的位置放错,一组测试数据运算完之后,没有得到刷新,导致累加。

2.倒数第五行的if(x!=n)粗心写成if(x=!n),没有及时检查出来。

总结:

多组数据输入的,对于需要刷新的数据,应该放在每一次的循环内部开始部分。

此种解法是先进行对位相加,然后再进行进位处理,这样做清晰明了,易于理解。下面是把两个工作同时做到。由于分离各个位上的数的操作,得到的是逆序的数字,意思就是54321这个数分离后是1 2 3 4 5,所以我采用的方式是在开始,就把a[],b[]各个字符转化为整型,逆序存入a1[],b1[]中。最后还是逆序输出s[i]。


[plain]     view plain     copy    
    
    print   ?    
1. #include <stdio.h>  
2. #include<string.h>  
3. int main()  
4. {  
5.     chara[1001], b[1001];  
6.     intn, i, lena, lenb, len_max, x = 1, k;  
7.     scanf("%d",&n);  
8.     getchar();  
9.     while(n--)//对应下面对输出格式的限定(if(n >= 1) printf("\n");)  
10.     {  
11.         inta1[10001] = {0}, b1[10001] = {0}, s[20002] = {0};  
12.         scanf("%s",a);  
13.         lena= strlen(a);  
14.         //转为数字,逆序保存  
15.         for(i= 0; i <lena;i++)  
16.             a1[i]= a[lena - 1 - i] - '0';  
17.         scanf("%s",b);  
18.         lenb= strlen(b);  
19.         for(i= 0; i <lenb;i++)  
20.             b1[i]= b[lenb - 1 - i] - '0';  
21.         if(lena> lenb)  
22.             len_max= lena;  
23.         else  
24.             len_max= lenb;  
25.         k= 0;  
26.         //变加边实现进位(关键看这里)  
27.         for(i= 0; i <len_max ;i++)  
28.         {  
29.             s[i]= (a1[i] + b1[i] + k) % 10;  
30.             k= (a1[i] + b1[i] + k) / 10;  
31.         }  
32.         //最高位的进位情况  
33.         if(k!= 0) s[len_max] = 1;  
34.         printf("Case%d:\n", x);  
35.         x++;  
36.         printf("%s+ %s = ", a, b);  
37.         if(s[len_max]== 1)  
38.             printf("1");  
39.         for(i= len_max - 1; i >= 0;i--)//逆序输出  
40.         {  
41.             printf("%d",s[i]);  
42.         }  
43.         printf("\n");  
44.         if(n>= 1) printf("\n");  
45.     }  
46.     return0;  
47. }