C语言大数问题

关于大数学习的一些小思路:

    (    本文以大数整数加法为例)

        从小学开始我们就一直在学习加减乘除,很多场合下我们都能够运用自如,并且理论上如果我们休息充足,材料充足而且大脑不短路,手速快的情况下,我们可以算出来任意长度的两个数字的加减乘除的结果,但是毕竟现实当中我们是没有这么多时间的,人的一生很短暂,于是我们便要把这个重任交给我们手中的计算机来解决啦~

        那么在学习大数整数加法思路以前,我们先来回想一下我们列竖式计算两个数字和的过程:

1. 分两行写下两个数字,右对齐。

2. 从个位开始,将对应位置上的数字相加,结果如果大于十,进一。

3. 将本位结果减10写下来。

4. 如果后一位有进位,执行完2后,执行3。

5. 重复2-4,直到所有位上的数字全部相加,如果位数不同,没有数字位补0.

        很好,至此,一个完整的加法过程已经呈现在了我们的眼前,如果你想更加仔细地复习一下这个过程,不妨去百度一下小学生的加法练习题。

        到这里有可能有的读者就会问了,那我学大数加法,你这给我整个小学的知识干嘛?糊弄我玩儿呢?

        非也,须知,大数大数,在我们的学习当中代指位数很多的数字,我们都知道,在计算机当中,默认提供的几种数据类型范围都是有限的,比如正常的int类型也只支持到21亿多一点,可如果我加一位呢?200亿该怎么计算呢?达到了计算机提供的上限我就不能计算了吗?

        当然不是,事实上,我们刚才复习的加法过程,便可以解决任意数位的整数加法问题不是吗?既然有了计算方法,我们便只需要将它教给电脑即可咯~

        我喜欢把这个过程比作为:将人的思路赋予电脑。

        电脑是个乖孩子,它的学习速度很快,准确说,只要给定代码他就可以瞬间学习。

        下面来看一下我们怎么把这个东西教给我们的机器学生吧:

        首先,在C语言的默认数据类型当中,有两个类型紧密相连,它们是字符型和整形(琐碎的基础知识比如ASCII码,以及它如何将整形字符型连接起来的的请读者自行学习,这里不再赘述)。那么有了这两个数据类型,我们便有了以下思路。

        我们知道整形只能储存21亿大一点的数字,哪怕再多一位都不行。但是,字符型数组就不一样了,如果一个数组元素写作一个数字的话,那么我们会发现,我们居然可以储存成百上千万位的数字!当然如果你以后再学习一些东西,你会发现,能计算多大的数字完全取决于你的硬盘容量!多么令人兴奋的事情!

        也就是说,我们用一个字符型数组存储一个很大的数字,这样我们就做到了“把第一个数字写在纸上”,那么怎么把第二个数字也写在纸上呢?用第二个字符数组不就得了嘛~

例:

char s1[1000], s2[1000];

scanf("%s %s", &s1, &s2);

        很好!你已经有了这些数字,那么接下来就是计算了!

        至于计算,相信你不难发现,如果直接用字符型进行计算不仅麻烦,而且容易出错,代码繁杂,难以理解。那么此时,对两个字符型数组,我们用两个整形数组把他们存起来,而且要倒序存储!(思考一下为什么要倒序存下来)具体做法就是用上ASCII码这个小工具啦~当然还得写上一行#include

        很好,现在我们算是处理完了两个数字,并且倒序存储了下来,也就说我们可以开始计算了!

        从第一位开始,所有位都相加,如果本位满十进一,本位减十。有哪一位没有数字就补0。

        你会发现,如果原本的数字最长是N位的话,那么加出来的数字最长也就是N+1位而已(思考一下为什么),所以我们再建立一个整形数组,把计算出来的结果从上面两个整形数组里面再倒序取出来,负负得正,两次倒序,数字又正回来了,然后就是从最高位到最低位输出换行即可啦~

        那么现在,到了给出代码的时间啦~

#include
#include
char s1[1000], s2[1000];
int n1[1000], n2[1000];//全局变量默认为所有元素初始值为0
int sum[1010];//同上
int main()
{
	while (scanf("%s %s", &s1, &s2) != EOF)//多组实例测试,让你加个够~
	{
		memset(n1, 0, sizeof(n1));
		memset(n2, 0, sizeof(n2));//每次计算要先把整形数组所有位归零,别忘啦
		for (int i = 0; i < strlen(s1); i++)//第一个数字倒序存入整形数组n1
		{
			n1[i] = s1[strlen(s1) - 1 - i] - '0';
		}
		for (int i = 0; i < strlen(s2); i++)//第二个倒序存入n2
		{
			n2[i] = s2[strlen(s2) - 1 - i] - '0';
		}
		for (int i = 0; i < (strlen(s1) >= strlen(s2) ? strlen(s1) : strlen(s2)); i++)//开始愉快的加法环节~
		{
			sum[i] = n1[i] + n2[i];//一位一位加,不能一口吃个胖子
			if (sum[i] >= 10)//然后就是进位检查啦
			{
				sum[i + 1]++;
				sum[i] -= 10;
			}
		}
		for (int i = (strlen(s1) >= strlen(s2) ? strlen(s1) : strlen(s2)); i >= 0; i--)//在这里我们从可能的最高位开始检查
		{
			if (sum[i] != 0)//直到某位不为0
			{
				for (int j = i; j >= 0; j--)//然后一口气输出吧!
				{
					printf("%d", sum[j]);
				}
				break;//然后呢?跳出外层for啦~
			}
		}
		printf("\n");//换个行,回家吃饭~
	}
	return 0;
}

你可能感兴趣的:(ACM,算法)