1. 程式人生 > >C語言大數問題

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<string.h>

        很好,現在我們算是處理完了兩個數字,並且倒序儲存了下來,也就說我們可以開始計算了!

        從第一位開始,所有位都相加,如果本位滿十進一,本位減十。有哪一位沒有數字就補0。

        你會發現,如果原本的數字最長是N位的話,那麼加出來的數字最長也就是N+1位而已(思考一下為什麼),所以我們再建立一個整形陣列,把計算出來的結果從上面兩個整形數組裡面再倒序取出來,負負得正,兩次倒序,數字又正回來了,然後就是從最高位到最低位輸出換行即可啦~

        那麼現在,到了給出程式碼的時間啦~

#include<stdio.h>
#include<string.h>
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;
}