大整數乘法以及空間性能優化

        在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;
}



發佈了11 篇原創文章 · 獲贊 8 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章