2013-12-23 82 views
3

有人可以用一點時間,他可以向我解釋如何激烈非常大的數字?我在這裏不是在談論現成的解決方案,而是如何實現算術的唯一解釋。理想情況下,它基於類std :: string。C++中功耗非常大的數字

@edit

我看了一些關於移位,但它的實例爲只在上市的形式,我想它是如何工作的解釋。

+1

搜索大整數庫。然而,實際上沒有解決方案將基於std :: string,因爲這是低效的。寫你自己的,或者將每個數字串聯起來。 – stefan

+0

您必須將數字聲明爲數組...數組的每個元素指向數字的一個數字 – AminM

+0

如果您計劃實現我們自己的(並且您會瘋了,因爲已經有很多實現)會鼓勵您爲您的數據類型使用常規縮放器的矢量,並編寫用於轉換爲/從「std :: string」轉換的轉換器。當你不必經常爲每個數據執行'(arg [n] - '0')時,你會發現數學部分相當容易合併。結果代碼將*相當容易維護。 – WhozCraig

回答

3

以下是我在需要時快速寫下的內容(不記得何時)。它是:

  1. 越野車;
  2. 不完整;
  3. 任意使用每個數組元素3個數字,而它可以使用更多;
  4. 可以明顯改善(歡迎任何種類的評論^^)。

但是,我希望這會有所幫助。

typedef long long int lli; 

class BigInt 
{ 
public: // Methods 
    BigInt(lli s) : m_nbElements(100) 
    { 
     m_number.resize(m_nbElements); 

     for (lli i=0; i < m_nbElements; ++i) 
     { 
      m_number[i] = s%1000; 
      s /= 1000; 
     } 
    } 

    BigInt(const std::string &str) : m_nbElements(100) 
    { 
     m_number.resize(m_nbElements); 

     size_t sizeStr = str.size(); 
     int i = str.size() - 1; 
     int thousands = 0; 
     for (; i >= 2; i -= 3, ++thousands) 
     { 
      std::string subStr = str.substr(i-2, 3); 
      unsigned int value; 
      std::istringstream(subStr) >> value; 
      m_number[thousands] = value; 
     } 

     // Handle the "first" 1 or 2 digits 
     if (i >= 0) 
     { 
      std::string subStr = str.substr(0, i+1); 
      unsigned int value; 
      std::istringstream(subStr) >> value; 
      m_number[thousands] = value; 
     } 
    } 

    BigInt operator*(lli s) 
    { 
     lli temp, remainder = 0; 
     for (lli i=0; i < m_nbElements; ++i) 
     { 
      temp = m_number[i] * s + remainder; 
      m_number[i] = temp % 1000; 
      remainder = temp/1000; 
     } 

     return (*this); 
    } 

    BigInt operator/(lli s) 
    { 
     lli temp, remainder = 0; 
     for (int i=m_nbElements-1; i >= 0; --i) 
     { 
      temp = (m_number[i] + remainder)/s; 
      remainder = (m_number[i] % s)*1000; 
      m_number[i] = temp; 
     } 

     return (*this); 
    } 

    BigInt operator-(BigInt s) 
    { 
     lli temp; 
     for (unsigned int i=0; i < m_nbElements; ++i) 
     { 
      temp = m_number[i] - s.m_number[i]; 
      if (temp < 0) 
      { 
       --m_number[i+1]; 
       temp += 1000; 
      } 
      m_number[i] = temp; 
     } 

     return (*this); 
    } 

    BigInt operator+(BigInt s) 
    { 
     lli temp, remainder = 0; 
     for (lli i=0; i < m_nbElements; ++i) 
     { 
      temp = m_number[i] + s.m_number[i] + remainder; 
      m_number[i] = temp % 1000; 
      remainder = temp/1000; 
     } 

     return (*this); 
    } 

    std::string ToString() 
    { 
     std::string result = ""; 
     bool significantDigitsFound = false; 
     for (int i=m_nbElements-1; i >= 0 ; --i) 
     { 
      if (!significantDigitsFound) 
      { 
       if (m_number[i] > 0) 
       { 
        std::ostringstream ss; 
        ss << m_number[i]; 
        result = ss.str(); 

        significantDigitsFound = true; 
       } 
      } 
      else 
      { 
       std::ostringstream ss; 
       ss << std::setw(3) << std::setfill('0') << m_number[i]; 
       result += ss.str(); 
      } 
     } 

     if (result == "") 
     { 
      result = "0"; 
     } 

     return result; 
    } 

private: // Attributes 
    int m_nbElements; 
    std::vector<lli> m_number; 
}; 
4

您可以將一個大數字表示爲一些基數中的數字序列,並分別表示數字的符號。要做算術運算,你只需要實現你在小學學到的算法來進行加法運算,長乘法運算等等。有一些操作可以使用更高效的算法(例如Karatsuba),但是最初的實現可以使用更簡單的形式。

如果您確實需要使用std :: string,則可以使用第一個字符來存儲符號('+'或' - '),然後使用ascii中的10進制數字。這種方式效率不高,但它可能是一種簡單的入門方式,它的確讓打印數字變得簡單。