大數乘法問題(C++版)

吳尼瑪發表於2017-12-19

近日參加一個筆試,遇到大數乘法問題,這是一個經典的演算法題。所謂大數乘法問題其實就是這樣的:輸入兩個整數,要求輸出這兩個數的乘積。輸入的數字可能超過計算機內任何資料的儲存範圍。這裡主要需要注意的點就是需要使用字串或者字元陣列來儲存這兩個大數以及他們的結果,還有乘法計算過程中存在乘法進位和加法進位。

我先自己嘗試寫了一個答案,思路就是模擬手寫豎式乘法。

    static string MYMULTIPLY(const string &number1, const string &number2)
	{
		int length1 = number1.size();
		int length2 = number2.size();
		string result = "";

		if (length1 == 0 || length2 == 0)
		{
			result = "error";
			return result;
		}

		int *iresult;
		iresult = (int*)malloc(sizeof(int) * (length1 + length2 + 1));
		memset(iresult, 0, sizeof(int) * (length1 + length2 + 1));

		for(int i = length1 - 1, x = 0; i >= 0; i--, x++)
		{
			int numA = number1[i] - 48;
			int value1 = 0;
			int value2 = 0;
			int multiFlag = 0;//乘法進位數
			int addFlag = 0;//加法進位數

			for(int j = length2 - 1, y = 0; j >= 0; j--, y++)
			{
				int numB = number2[j] - 48;
				value1 = numA * numB + multiFlag;
				multiFlag = value1 / 10;
				value1 = value1 % 10;
				value2 = (iresult[x+y]) + value1 + addFlag;
				addFlag = value2 / 10;
				iresult[x+y] = (value2 % 10); 
			}
			iresult[x + length2] += (multiFlag + addFlag);
		}

		//逆序
		int i = 0;
		for(i = length1 + length2 - 1; i >= 0; i--)
		{
			if(iresult[i] != 0)
				break;
		}

		for(; i >= 0; i--)
		{
			result = result + (char)(iresult[i]+48);
		}

		free(iresult);

		return result;
	}
複製程式碼

這個方法雖然能得出結果,但是太難看了,特別是計算每一位相乘的結果和進位的那一段程式碼。之後,我就把這段程式碼改進了一下,將每一位之間的乘法和進位計算分開來。

    static string MULTIPLY(string number1, string number2)
	{
		int i, j;
		int *iresult;
		int length1 = number1.size();
		int length2 = number2.size();
		string result = "";

		reverse(number1.begin(), number1.end());
		reverse(number2.begin(), number2.end());

        if (length1 == 0 || length2 == 0)
		{
			result = "error";
			return result;
		}

		iresult = (int*)malloc(sizeof(int) * (length1 + length2 + 1));
		memset(iresult, 0, sizeof(int) * (length1 + length2 + 1));

        //每一位相乘
		for(i = 0; i < length1; i++)
		{
			for(j = 0; j < length2; j++)
			{
				iresult[i+j] += ((number1[i] - 48) * (number2[j] - 48));
			}
		}

        //進位運算
		int carry = 0;
		for(i = 0; i < length1 + length2; i++)
		{
			int value = iresult[i] + carry;
			iresult[i] = value % 10;
			carry = value / 10;
		}

		for(i = length1 + length2 - 1; i >= 0; i--)
		{
			if(iresult[i] != 0)
            break;
		}

		for(; i >= 0; i--)
		{
			result = result + (char)(iresult[i]+48);
		}

		free(iresult);

		if(result == "") result = "0";
		return result;
	}
複製程式碼

當然這個問題還有分治乘法,快速傅立葉等演算法,這個就不是在筆試或者面試的時候能快速寫出來的了。有興趣大家可以繼續深入瞭解下。