1. 程式人生 > >大整數的加法和乘法運算

大整數的加法和乘法運算

C和C++中整數最大隻能表示10位,不然就會溢位,所以出現瞭如何避免整數溢位的問題。其中一個方法就是使用字串來表示,使用字串的長度是沒有限制的。

使用字串表示整數然後進行乘法運算的關鍵有如下幾點:

  1. 被乘數和乘數相乘時最開始不處理進位,而是每一位相乘的計算結果都是用整數來儲存
  2. 第一步計算完畢之後從低位到高位開始處理進位
  3. 不難發現儲存計算結果的整型陣列的長度是被乘數的長度和乘數的長度之和
  4. 注意最高位的進位問題
  5. 將計算完畢後的整形陣列轉換成字元陣列
  6. 字元陣列尾端記得加上\0,整型轉字元型時記得加上'0'
基本的演算法步驟使用下面的圖示來說明:(下面都是針對正整數的運算)
程式碼實現如下:
// Test9.cpp : 定義控制檯應用程式的入口點。
//

#include <iostream>
#include <assert.h>
#include <sstream>
using namespace std;

void multiply(const char * str1,const char * str2)
{
	assert(str1!=NULL&&str2!=NULL);
	int cstr1=strlen(str1);
	int cstr2=strlen(str2);
	int * res=new int[cstr1+cstr2]();//注意new關鍵詞尾端加上小括號就會將res初始化為0,特別注意小括號裡不能填任何初值

	//逐位處理,處理遍歷字串是從低位到高位,那麼運算結果就是從整數的高位開始計算
	for (int i=0;i<cstr1;i++)
	{
		for (int j=0;j<cstr2;j++)
		{
				res[i+j+1]+=int(str1[i]-'0')*int(str2[j]-'0');//首先計算的是高位,res要加上1是為了處理後面的偏移
		}
	}

	//處理進位
	for (int i=cstr1+cstr2-1;i>=1;i--)
	{
		if(res[i]>=10)
		{
			res[i-1]+=res[i]/10;
			res[i]=res[i]%10;
		}
	}

	//將int型陣列儲存成字元陣列
	char * ans=new char[cstr1+cstr2];
	
	int k=0;
	while(res[k]==0)//首先需要掉過為0的那些高位
		k++;

	int pos=0;
	while(k<cstr1+cstr2)//執行復制操作
	{
			ans[pos++]=res[k++]+'0';//不要忘記了加上'0'
	}
	ans[pos]='\0';//最後記得字元陣列尾端需要補上字串結束標記
	cout<<"計算結果為:";
	for (int i=0;i<strlen(ans);i++)
	{
		cout<<ans[i];
	}
	cout<<endl;
	delete [] res;
	delete [] ans;
}
int main()
{
	string s;
	stringstream ss;
	cout<<"輸入兩個數,以空格隔開:"<<endl;
	while(getline(cin,s))
	{
		ss.clear();
		ss<<s;
		string s1,s2;
		ss>>s1>>s2;
		multiply(s1.c_str(),s2.c_str());
	}
	getchar();
	return 0;
}

測試輸出:
同樣的思路可以處理大整數的加法: 關鍵的函式如下:
void add(const char * str1,const char * str2)
{
	assert(str1!=NULL&&str2!=NULL);

	int  cstr1=strlen(str1);
	int cstr2=strlen(str2);
	int maxLen=max(cstr1,cstr2)+1;
	int * res=new int[maxLen]();
	int minLen=min(cstr1,cstr2);

	int k=0;
	int i=cstr1-1,j=cstr2-1 ;
	//從字串尾端開始遍歷起,將結果儲存在res陣列中
	for (;i>=0&&j>=0;i--,j--)
	{
		res[k]=str1[i]-'0'+str2[j]-'0';
		k++;
	}

	//對於較長的字串,直接將它新增到res尾端即可
	while (i>=0)
		res[k++]=str1[i--]-'0';

	while(j>=0)
		res[k++]=str2[j--]-'0';

	//處理進位
	for (int m=0;m<maxLen-1;m++)
	{
		res[m+1]+=res[m]/10;
		res[m]=res[m]%10;
	}

	//將結果集的高位去除
	k=maxLen-1;
	while(res[k]==0)
			k--;

	char * ans=new char[maxLen];
	int m=k,n=0;
	//需要從res陣列中從高位開始取數
	for (;m>=0;m--,n++)
	{
		ans[n]=res[m]+'0';
	}
	ans[n]='\0';
	cout<<"計算結果為:"<<ans<<endl;
}

測試輸出: