在C++版的數據結構中有一道課後練習題—大整數求和,不過這次我想弄的是大整數乘法並對它進行空間性能優化一下,因爲書本上的一個int類型只能存放0~9的數字,很容易造成空間上的浪費,這次我的一個int類型存放4位數字,不過在實現之前我們還是做一下大整數加法,畢竟要先從容易的入手,題目如下所示:
用某種程序設計語言進行編程時,可能需要處理非常大或者運算精度要求非常高的整數(稱爲大整數),這種大整數用該語言的基本數據類型是無法直接表示的。處理大整數的一般方法是用數組存儲大整數,數組元素代表大整數的一位,通過數組運算模擬大整數的運算。
以上爲題目: 首先我來說一下我的解題思路:
1. 創建一個char類型的數組,接收鍵盤的輸入,當然我也百度了一下其他人的博客,他們都是直接建立int類型的數組的,其實這樣子並不是很好,因爲當我們輸入123時,如果直接用int類型數組,每輸入一個數子都要加一個空格分開了,即輸入1 2 3,這樣子會導致輸入很不方便,所以這次我用的是char數組再轉換爲int數組。
2. 數組的中的排序爲從低位到高位,即123在數組用321來表示,因爲加法運算時是從低位算起的。
具體代碼如下:
#include <iostream>
#include <cstring>
using namespace std;
const int Max_size = 100000;
int num1[Max_size];
int num2[Max_size];
int sum[Max_size];
//加法函數
void add(){
int max;
//爲了方便相加,將數組長度短的後面初始化爲0
if(num1[Max_size-1]<num2[Max_size-1]){
for(int i=num1[Max_size-1];i<num2[Max_size-1];i++){
num1[i] = 0;
}
max = num2[Max_size-1];
}else{
for(int i=num2[Max_size-1];i<num1[Max_size-1];i++){
num2[i] = 0;
}
max = num1[Max_size-1];
}
sum[Max_size-1] = max;
for(int i=0;i<max-1;i++){
sum[i] = num1[i]+num2[i];
//進位
//感覺當時應該把num1,num2傳進來的,現在num1已經被污染了
//(PS: 不能以int* 的方式傳數組,因爲以指針的方式一樣會被污染的)
if(sum[i]>9){
sum[i] -= 10;
num1[i+1]++;
}
}
sum[max-1] = num1[max-1]+num2[max-1];
if(sum[max-1]>9){
sum[max-1] -= 10;
sum[max] = 1;
sum[Max_size-1]++;
}
}
int main(){
char num[Max_size]; //輸入的字符轉換爲數字
cin>>num;
//將數組的高位存放數字的低位
for(int i=strlen(num)-1;i>=0;i--){
//將char類型隱式轉換爲int類型
num1[strlen(num)-1-i] = num[i]-'0';
//這是一個錯誤的示範,其實應該將strlen(num) 賦值給一個整型的
//因爲用一個調用strlen()函數真的很耗性能
}
//用數組的最後一個存放該數組的長度
num1[Max_size-1] = strlen(num);
//給num2數組賦值,重複以上步驟
cin>>num;
for(int i=strlen(num)-1;i>=0;i--){
num2[strlen(num)-1-i] = num[i]-'0';
}
num2[Max_size-1] = strlen(num);
add();
for(int i=sum[Max_size-1]-1;i>=0;i--){
cout<<sum[i];
}
return 0;
}
上面爲大整數加法,下面來討論大整數乘法,在實現之前先說一下我的思路:
1. 當我們輸入123456789(char類型)時,6789存放在int[0]中,2345存放在int[1]中,1存放在int[2]中,因爲輸入的char類型,所以要將四個字符轉爲四位數字(即千位數),但前面都是存放4個字符,可以用統一的代碼來實現,但最後一個1只有一個字符,需要特殊處理一下。(其實也不用這樣處理的,只需在char數組前留空幾個字符就可以,可以參考一下鏈表中使用空頭結點來統一代碼的思路)
2. 當輸出結果時,有些存放的數字是0123,真正輸出的是123,所以要做一些處理,將其轉換一下。
3. 剛開始做這道題時,我以爲跟大整數求和的差不多,其實這道題並是很簡單的,有很多需要注意的問題,有興趣的可以做下。
具體代碼如下:
#include <iostream>
#include <cstring>
using namespace std;
const int Max_size = 10000;
char num[Max_size*4];
int num1[Max_size] = {0};
int num2[Max_size] = {0};
int sum[Max_size*2] = {0};
int num1_len,num2_len,sum_len,num_len;
void char_to_int(int i,int* a){
int n=1;
int temp=num_len-1-4*i;
if(temp<3) //遞歸的結束條件
return;
for(int j=0;j<4;j++){
int m = num[temp] - '0';
*a += n*m;
n *= 10;
temp--;
}
char_to_int(++i,++a);
}
void mutil(){
sum_len = 0;
for(int i=0;i<num1_len;i++){
for(int j=0;j<num2_len;j++){
long n = num1[i]*num2[j];
sum[i+j] += n%10000;
sum[i+j+1] += n/10000;
if(sum_len<i+j+2){
sum_len = i+j+2;
}
if(sum[i+j]>9999){
sum[i+j] -= 10000;
sum[i+j+1] += 1;
}
}
}
if(!sum[sum_len-1]){
sum_len--;
}
}
int main(){
int start,n,m;
cin>>num;
num_len = strlen(num);
start = num_len%4-1;
num1_len = (num_len-1)/4+1;
n = 1;
while(start != -1){
m = num[start] - '0';
num1[num1_len-1] += n*m;
n *= 10;
start--;
}
//這次我用的遞歸函數處理...(傳入的i爲給第i個數組賦值)
char_to_int(0,num1);
//重複上述步驟,給num2賦值
cin>>num;
num_len = strlen(num);
start = num_len%4-1;
num2_len = (num_len-1)/4+1;
n = 1;
while(start != -1){
m = num[start] - '0';
num2[num2_len-1] += n*m;
n *= 10;
start--;
}
char_to_int(0,num2);
mutil();
cout<<sum[sum_len-1];
for(int i=sum_len-2;i>=0;i--){
if(sum[i]<10){
cout<<"000";
}else if(sum[i]<100){
cout<<"00";
}else if(sum[i]<1000){
cout<<"0";
}
cout<<sum[i];
}
return 0;
}