高精度运算之加法

原题:

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就可以解决。

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

分析:

首先这是一个加法问题。

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

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

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

#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

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

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

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

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

代码如下:

#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]

#include <stdio.h>
#include<string.h>
int main()
{
	chara[1001], b[1001];
	intn, i, lena, lenb, len_max, x = 1, k;
	scanf("%d",&n);
	getchar();
	while(n--)//对应下面对输出格式的限定(if(n >= 1) printf("\n");)
	{
		inta1[10001] = {0}, b1[10001] = {0}, s[20002] = {0};
		scanf("%s",a);
		lena= strlen(a);
		//转为数字,逆序保存
		for(i= 0; i <lena;i++)
			a1[i]= a[lena - 1 - i] - '0';
		scanf("%s",b);
		lenb= strlen(b);
		for(i= 0; i <lenb;i++)
			b1[i]= b[lenb - 1 - i] - '0';
		if(lena> lenb)
			len_max= lena;
		else
			len_max= lenb;
		k= 0;
		//变加边实现进位(关键看这里)
		for(i= 0; i <len_max ;i++)
		{
			s[i]= (a1[i] + b1[i] + k) % 10;
			k= (a1[i] + b1[i] + k) / 10;
		}
		//最高位的进位情况
		if(k!= 0) s[len_max] = 1;
		printf("Case%d:\n", x);
		x++;
		printf("%s+ %s = ", a, b);
		if(s[len_max]== 1)
			printf("1");
		for(i= len_max - 1; i >= 0;i--)//逆序输出
		{
			printf("%d",s[i]);
		}
		printf("\n");
		if(n>= 1) printf("\n");
	}
	return0;
}




 

完。

请指教!

期待你的鼓励哦!


评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值