c++算法之500位的整數相乘

遇到這樣一道算法題:

題目

計算兩個非負整數 A,,B 的乘積,A,B 可能會很大;

輸入

第一行輸入一個非負整數 A。

第二行輸入一個非負整數 B。

A,B 的長度不大於 500。

輸出格式

輸出A * B的值

分析:

題目的要求是兩位500位以內的整數相乘,所以根據現有的數據類型,無法直接算出答案,需要另尋它徑。初步分析,考慮最極限的情況,可以經過推理得到:比如2個兩位數相乘產生的最大的數爲4位;兩個3位數相乘的最大結果爲6位;兩個4位數相乘的最大值是8位....;因此兩位500位的數相乘之後所能產生的最大的數是1000位;因此,分析到這裏,我們就需要用一個長度爲1000的數組和兩個長度爲500得數組來保存結果和輸入值。

此外,分析乘法的運算,之前已經提過,利用現有的數據類型無法直接得出答案。所以我們分析乘法的具體步驟。回想起之前學過的計算機組成原理的上機實驗,在機器底層的加減乘除法,都是一位一位操作,然後通過位移的方式來循環判斷,直至運算結束。所以這裏我直接套路了之前的用法,用最原始的方法(就是筆算的方法),一位乘以一位的操作計算機可以幫我們完成。因此我們可以假設一波,比如計算:12344321 *  1999123,首先我們是用第二個數的末尾數字去乘第一個數,挨個乘每一位,遇到進位要加進位;也就是12344321 * 3,然後又是倒數第二個數乘以第一個數:12344321 * 1 ......;通過循環往復,最後把第二個數字的第一位乘以第一個數就完成了第一步。第二步,我們需要將之前乘法得到的數做加法,並且每次加法都要錯位(其實也相當於位移一個了)。將所有得到的數相加完畢之後,我們就能得到我們想要的結果。先附上完整代碼:


#include<iostream>
#include<stdlib.h>
#include<string>
int tmp[501] = { 0 };
using namespace std;
/*
此部分用來做乘法,也就是將乘數的某一位與被乘數整體相乘;
其步驟依然是一位一位乘;
參數分別是是被乘數,乘數的某一位,進位值;
*/
void mutiply(int a[], int bi, int pre)
{
	for (int i = 499; i >= 0; i--)
	{
		tmp[i + 1] = (a[i] * bi + pre) % 10;
		pre = (a[i] * bi + pre) / 10;
	}
}
/*
此部分做錯位加法,上一步得到的值通過錯位的方式與answer的相應位置相加;
參數分別是答案,答案下標;
其中局部變量indexTMP 代表tmp數組的下標;
pre代表進位值;
*/
void add(int answer[], int indexAnswer)
{
	int indexTMP = 500;
	int pre = 0;
	while (indexTMP >= 0)
	{
		int value = answer[indexAnswer] + tmp[indexTMP] + pre;
		answer[indexAnswer] = (answer[indexAnswer] + tmp[indexTMP] + pre) % 10;
		pre = value / 10;
		indexAnswer--;
		indexTMP--;
	}

}
/*
此部分調用以上兩部分功能,通過循環來實現整體的乘法
參數分別是:被乘數,乘數,答案
*/
void function(int a[], int b[], int answer[])
{
	for (int i = 499; i >= 0; i--)
	{
		mutiply(a, b[i], 0);
		add(answer, i + 500);
	}
}
int main()
{
	string a;
	string b;
	string c;
	cin >> a;
	cin >> b;
	int a1[500] = { 0 };
	int b1[500] = { 0 };
	int answer[1000] = { 0 };
	int maxlength = a.length();
	int minlength = b.length();
	if (maxlength < minlength)
	{
		int tmp = minlength;
		minlength = maxlength;
		maxlength = tmp;
	}
    /*
    此部分是將字符串的數值轉化到int型數組中
    */
	for (int i = a.length() - 1, j = 499; i >= 0; i--, j--)
	{
		a1[j] = a[i] - 48;
	}
	for (int i = b.length() - 1, j = 499; i >= 0; i--, j--)
	{
		b1[j] = b[i] - 48;
	}

	function(a1, b1, answer);
/*
不輸出前面多餘的0,從真正有意義的數值開始輸出,index用來記錄該下標
*/
	int index = 0;
	for (int i = 0; i <= 999; i++)
	{
		if (answer[i] != 0)
		{
			index=i;
			break;
		}

	}
	if(index!=0)
	{
		for (int k=index; k < 1000; k++)
		{
			cout << answer[k];
		}
	}
	else
	{
		cout << "0";
	}
	system("pause");
	return 0;
}

注意,本程序涉及全局變量tmp[501],改變量用來保存乘數的某一位乘以被乘數所得到的值,其最大爲501位;此外,在function裏,add方法的調用,第二個參數是i+500;這裏保證了每一次相加時的錯位,也就是相當於相加時tmp相對於answer整體左移一位,符合筆算的規則。

編譯執行結果:

500位以內正整數隨便乘,當然也可以改成正負數都可以,這裏就不演示了,如有疑問歡迎評論區留言,歡迎大家轉載! 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章