高精度之加法

来源:互联网 发布:ubuntu修改文件夹权限 编辑:程序博客网 时间:2024/06/07 00:31

原题:

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. }  



 

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

度娘告诉你,这一类的问题有一个高大上的名字,叫做高精度运算。她还告诉你,遇到这种情况,你可以利用的数据类型有两种,一种是字符串,另一种是数组。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. }  




 

我的错误:

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. }