2015-04-24 37 views
0

在這裏,我有一個SafeArray(不是那麼安全,但我的老師說這很好)class和bigint類。我的bigint類可以添加和減少就好,但是當我嘗試乘法函數時,它根本不打印任何東西,我試過調試並逐步通過它,但我似乎無法弄清楚,一直在努力一段時間,我絕望地卡住了。任何幫助,將不勝感激。由於在數組C++中乘以大字符串

 #include <iostream> 
     using namespace std; 
#include <algorithm> 

template<typename Element> 
class SafeArray 
{ 
    int size; 
    Element*Array; 
    Element def; 

public: 
    SafeArray()       //default constructor(with no parameter) 
    { 
     size = 10; 
     Array = new Element[size](); 
    } 

    SafeArray(int value)   //constructor with one int 
    { 
     size = value; 
     Array = new Element[value]; 
     for (int i = 0; i < size; ++i) 
      Array[i] = 0; 
    } 

    ~SafeArray() { 
     delete[] Array; 
    }          //destructor 

    SafeArray(const SafeArray& rhs) : size(rhs.size), Array(new Element[size]), def(rhs.def) 
    { 
     for (int i = 0; i < size; ++i) 
      Array[i] = rhs.Array[i]; 
    } 

    SafeArray& operator=(SafeArray rhs) 
    { 
     std::swap(Array, rhs.Array); 
     std::swap(size, rhs.size); 
     std::swap(def, rhs.def); 
     return *this; 
    } 

    Element get(int pos) const     //get method 
    { 
     if (pos<0) 
     { 
      cout << "error"; 
     } 

     return Array[pos]; 
    } 

    void set(int pos, Element val) 
    { 
     if (pos<0) 
     { 
      cout << "error"; 
      return; 
     } 
     if (pos >= size) 
     { 
      resize(pos + 1); 
     } 
     Array[pos] = val; 
    } 

    void resize(int new_size) 
    { 
     Element*temp = new Element[new_size]; 
     for (int i = 0; i<size; i++) 
     { 
      temp[i] = Array[i]; 
     } 
     delete[]Array; 
     Array = temp; 
     size = new_size; 
    } 

    void set_default(Element d)  //set_default 
    { 
     def = d; 
    } 

    int get_size()      //get size 
    { 
     return size; 
    } 
}; 

int size = 100; //for testing 

class bigint 
{ 
    SafeArray<int> *arr; 
public: 
    bool sign; 
bigint()             //initializes to zero 
    { 
     arr = new SafeArray<int>; 
     for(int i =0;i < size; i++) 
      arr->set(i,0); 
    } 

void print()            //prints numbers without zeroes in front 
    { 
     bool start_num=false; 
     for(int i = 0;i <arr->get_size() ;i++) 
     { 
      if(arr->get(i)!=0 && start_num==false) 
      {start_num=true; 
       cout << arr->get(i);} 
     else if(start_num==true) 
      cout<<arr->get(i); 

     } 

     cout<<endl; 
    } 
    void assign(const bigint &A)        // 
{ 
    for(int i=0;i<arr->get_size();i++) 
    {               //Ways to initialize stuff 
     arr->set(i,A.arr->get(i)); 
    } 

} 
void assign(string num)         
    { 
     long len = num.length(); 
     int j=arr->get_size()-1; 
     for(long i=len-1;i>=0;i--) 
     { 
      arr->set(j,num[i]-48); 
      j--; 
     } 
    } 
void add_pos(const bigint &A)        //add big ints 
    { 
     int carry=0; 
     for(int i=size-1;i>=0;i--) 
      { 
       int result = arr->get(i)+A.arr->get(i)+carry; 
       arr->set(i,result%10); 
       carry=result/10; 
      } 
    } 

void sub_pos(const bigint &A) 
     { 
      int borrow=0; 
      for(int i=size-1;i>=0;i--) 
      { 
       int result = ((arr->get(i) - A.arr->get(i)-borrow)); 
       if(result<0) 
       { 
       arr->set(i,result +10); 
       borrow = 1; 
       } 
       else 
       { 
       arr->set(i,result); 
       borrow = 0; 
       } 
      } 
     } 


    void multiply(const bigint &A) 
     { 
      for(int i=size-1;i>=0;i--) 
       { 
        int carry=0; 

       for(int j=size-1;j>=0;j--) 
       { 
        int product=((arr->get(i)*A.arr->get(j))+carry); 
        arr->set(i+j,product%10); 
        carry=product/10; 
       } 
      } 
    } 

    } 

int main() 
{ 
bigint a,b; 
a.assign("1234"); 
b.assign("5678"); 
a.multiply(b); 
a.print(); 

return 0; 
} 
+0

在'multiply'函數中,外部循環,條件是否應該是'i <= 0'?你不是指'i> = 0'嗎? –

+0

耶我的壞。只是修復它。 – jack

+0

你的'SafeArray'類是不安全的。誰在教這個東西?沒有複製構造函數,沒有賦值運算符?它應該是「安全的」? – PaulMcKenzie

回答

0

鑑於意見和以下更改SafeArray

實現乘法http://coliru.stacked-crooked.com/a/0f22a24e04421ae1

一種方式是利用你說的已經工作,即bigint::add_posbigint::sub_pos做乘法的功能。目標是通過將m加入n-1次來模擬m * n。例如,4 * 34 + 4 + 4相同(我們向自己添加了4次2次)。

注意:如果您的要求是您必須完全獨立於現有功能編寫乘法代碼和/或使用不安全版本SafeArray,那麼此答案不會對您有所幫助,您將不得不做從頭開始。


預賽:

應該做的第一件事就是更換指針SafeArraybigint類的實際實例:

SafeArray<int> arr;

第二更改將在之內更改爲arr->arr. 10班。這應該是無縫的改變。

現在,第三個要做的是在bigint創建一個輔助函數,調用它is_zero以確定是否bigint代表0。你可以很容易地編寫循環,並確保做到這一點,在arr所有條目0 。該功能應該是const,即

bool is_zero() const;

最後一個變化是,你有你的bigint默認的構造函數中的錯誤。該錯誤是,您沒有初始化arr SafeArray以擁有size元素。您使用的默認,這是隻有10。爲了解決這個問題,初始化arrsize元素

bigint() : arr(size) 
{ 
    for (int i = 0; i < size; i++) 
     arr.set(i, 0); 
} 

我一直在你的全局變量size,但它確實應該從一個全球被刪除,您bigint類應該使用arr.get_size()來獲取數組的大小。


實現:

所以現在我們得到的multiply使用現有功能的實現。這是一種迂迴的方式,對於非常大的值可能會很慢。

讓我們的代碼:

void multiply(const bigint &A) 
{ 
    // check for multiplication by 0 
    if (A.is_zero()) 
    { 
     *this = A; // copy our paramter (which is 0) to this object 
     return; 
    } 

    bigint tempInt(*this); // our original value 
    bigint startVal(*this); // our running total 
    bigint startA(A); // our counter 
    bigint subtractor; 
    subtractor.assign("1"); // our decrementor for looping 

    // subtract one from the number of times we need to add 
    startA.sub_pos(subtractor); 

    // keep adding until the number of times we've added is 
    // sufficient 
    while (!startA.is_zero()) 
    { 
     // add to running total 
     startVal.add_pos(tempInt); 

     // subtract 1 from our counter 
     startA.sub_pos(subtractor); 
    } 

    // assign the final result to our object, and we're done 
    *this = startVal; 
} 

所以我們做了什麼?

首先我們檢查了乘法0.如果是這樣,那麼我們將所有東西都歸零並返回。

如果不是0的乘法,我們設置一個臨時bigint來保存我們的原始值(tempInt)。然後我們設置另一個bigint,它持有我們目前的「運行總數」(startVal)。我們建立了另一個bigint,它將保留我們的乘數startA。請注意我們如何使用複製構造函數從現有構造函數構造臨時bigint。如果你的SafeArray不是真正安全的(即你堅持使用原來的實現),這是不可能的。

現在,當我們需要保持我們添加的次數時,麻煩發生了。爲此,建立了名爲subtractor的第四個bigint,它所做的全部初始化爲1。我們需要這個幫助我們從bigint乘數中減去1(這是我們設計中bigint::sub_pos的作用)。

請注意,我們必須做所有這一切減去1,而不是使用簡單的int's。原因 - 如果傳遞給乘法的bigint是一個很大的數字,不適合intlong,那麼我們不能使用「傳統」C++整數類型。我們正在處理100位數字,可能沒有C++編譯器具有本機100位整數類型。

所以我們從乘數中減去1開始。如果乘數現在爲零,我們就不會循環(本質上,這需要乘以1的情況,但請參閱下面的進一步編輯,以獲得乘以1的優化方式)。

如果乘數大於0,所有我們現在要做的就是調用add_pos我們總的運行,直到我們的乘數變爲0。我們通過測試我們的倍增器,看它是否已通過調用is_zero每次達到0 while()條件。每次我們呼叫sub_pos時,都要從乘數中減去1。

工作是寫在紙上的一個高層次的看一下這個乘法函數是幹什麼的條件 - 你應該得到的是做什麼工作的想法(鬼祟地避免了必須實際編寫乘法代碼像你一樣在你的問題)。

最後,我們將運行總數分配給這個。而已。所有使用你現有的功能,再加上一個簡單的助手,並使你的班級更安全一些。

編輯: 您可以進行的優化是檢查乘法1.您的操作方法是設置計數器,從中減去1,然後檢查計數器是否爲0。如果它是0,則返回而不做任何進一步的工作。

+0

太棒了。謝謝您的幫助。 – jack

+0

我使用當前的'main'程序測試了這些更改,並獲得了'1522756'的正確輸出。 – PaulMcKenzie

+0

我測試了上述變化,你的'main'函數正確地進行了乘法運算。所以我們可以假設是的,你的'add_pos'和'sub_pos'函數可以工作。所以基本上,你做了大部分工作,你只需要有一個更好的SafeArray類(老師應該提供這個類),以及另一種查看乘法的方法。 – PaulMcKenzie