遇到這樣一道算法題:
題目
計算兩個非負整數 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位以內正整數隨便乘,當然也可以改成正負數都可以,這裏就不演示了,如有疑問歡迎評論區留言,歡迎大家轉載!