zoukankan      html  css  js  c++  java
  • 大整数模板

      稍微测试了一下感觉还行,可能有BUG,如果发现了还望告诉我。代码是C++11写的,要有能支持constexpr这些关键字的编译器才可以编译出来。

      update: 2016.8.5 15:51 加了个可以转出字符串的功能

     1 #pragma once
     2 #ifndef BigIntNums_H
     3 #define BigIntNums_H
     4 
     5 #include <vector>
     6 #include <iostream>
     7 #include <algorithm>
     8 #include <iomanip>
     9 #include <sstream>
    10 #include <string>
    11 #include <cstring>
    12 
    13 using std::reverse;
    14 using std::right;
    15 using std::left;
    16 using std::setw;
    17 using std::setfill;
    18 using std::stringstream;
    19 using std::string;
    20 
    21 using std::ostream;
    22 using std::istream;
    23 
    24 class BigIntNums;
    25 
    26 bool operator==(const BigIntNums &, const BigIntNums &);
    27 bool operator!=(const BigIntNums &, const BigIntNums &);
    28 bool operator<(const BigIntNums &, const BigIntNums &);
    29 bool operator>(const BigIntNums &, const BigIntNums &);
    30 bool operator<=(const BigIntNums &, const BigIntNums &);
    31 bool operator>=(const BigIntNums &, const BigIntNums &);
    32 ostream &operator<<(ostream &, const BigIntNums &);
    33 istream &operator>>(istream &, BigIntNums &);
    34 BigIntNums operator+(const BigIntNums &, const BigIntNums &);
    35 BigIntNums operator*(const BigIntNums &, const BigIntNums &);
    36 BigIntNums operator-(const BigIntNums &, const BigIntNums &);
    37 BigIntNums operator/(const BigIntNums &, const BigIntNums &);
    38 BigIntNums operator%(const BigIntNums &, const BigIntNums &);
    39 BigIntNums operator-(const BigIntNums &);
    40 BigIntNums abs(const BigIntNums &);
    41 
    42 class BigIntNums
    43 {
    44     friend ostream &operator<<(ostream &, const BigIntNums &);
    45     friend istream &operator>>(istream &, BigIntNums &);
    46     friend BigIntNums operator-(const BigIntNums &);
    47     friend BigIntNums operator+(const BigIntNums &, const BigIntNums &);
    48     friend BigIntNums operator*(const BigIntNums &, const BigIntNums &);
    49     friend BigIntNums operator-(const BigIntNums &, const BigIntNums &);
    50     friend BigIntNums operator/(const BigIntNums &, const BigIntNums &);
    51     friend BigIntNums operator%(const BigIntNums &, const BigIntNums &);
    52     friend bool operator<(const BigIntNums &, const BigIntNums &);
    53     friend bool operator>(const BigIntNums &, const BigIntNums &);
    54     friend bool operator<=(const BigIntNums &, const BigIntNums &);
    55     friend bool operator>=(const BigIntNums &, const BigIntNums &);
    56     friend bool operator==(const BigIntNums &, const BigIntNums &);
    57     friend bool operator!=(const BigIntNums &, const BigIntNums &);
    58 public:
    59     BigIntNums() = default;
    60     BigIntNums(const BigIntNums &);
    61     BigIntNums(const string &);
    62     BigIntNums(const int &);
    63     BigIntNums(const unsigned int &);
    64     BigIntNums(const long long &);
    65     BigIntNums(const unsigned long long &);
    66 
    67     operator bool();
    68     BigIntNums &operator++();
    69     BigIntNums &operator--();
    70     BigIntNums &operator=(const BigIntNums &);
    71     BigIntNums &operator+=(const BigIntNums &);
    72     BigIntNums &operator*=(const BigIntNums &);
    73     BigIntNums &operator-=(const BigIntNums &);
    74     BigIntNums &operator/=(const BigIntNums &);
    75     string getStr();
    76 private:
    77     static constexpr size_t gap_ = 10000;
    78     static constexpr size_t base_ = 10;
    79 
    80     std::vector<int> numMem;
    81     bool npFlag = true;
    82 
    83     void combineStrToBigInt(const string &);
    84     template<typename T>void loadNums(T);
    85     void clear();
    86 };
    87 
    88 template<typename T>void BigIntNums::loadNums(T num)
    89 {
    90     numMem.clear();
    91     while (num / gap_)
    92     {
    93         numMem.push_back(static_cast<int>(num%gap_));
    94         num /= gap_;
    95     }
    96     numMem.push_back(static_cast<int>(num));
    97 }
    98 
    99 #endif // BigIntNums_H
      1 #include "bigIntNum.h"
      2 
      3 ostream &operator<<(ostream &os, const BigIntNums &num)
      4 {
      5     if (num.npFlag == false)
      6         os << '-';
      7     os << num.numMem[num.numMem.size() - 1] << " ";
      8     os << setfill('0') << right;
      9     int cut = static_cast<int>(log10(BigIntNums::gap_));
     10     for(int i = num.numMem.size() - 2;i >=0 ;i--)
     11         os << setw(cut) << num.numMem[i] << " ";
     12     os << setfill(' ') << left;
     13     return os;
     14 }
     15 
     16 istream &operator>>(istream &is, BigIntNums &num)
     17 {
     18     num.clear();
     19     string str;
     20     is >> str;
     21     num.combineStrToBigInt(str);
     22     return is;
     23 }
     24 
     25 BigIntNums::BigIntNums(const BigIntNums &ob)
     26     :numMem(ob.numMem)
     27     , npFlag(ob.npFlag)
     28 { }
     29 
     30 BigIntNums::BigIntNums(const int &num)
     31 {
     32     loadNums(num);
     33     npFlag = num >= 0 ? true : false;
     34 }
     35 
     36 BigIntNums::BigIntNums(const unsigned int &num)
     37 {
     38     loadNums(num);
     39     npFlag = true;
     40 }
     41 
     42 BigIntNums::BigIntNums(const long long &num)
     43 {
     44     loadNums(num);
     45     npFlag = num >= 0 ? true : false;
     46 }
     47 
     48 BigIntNums::BigIntNums(const unsigned long long &num)
     49 {
     50     loadNums(num);
     51     npFlag = true;
     52 }
     53 
     54 BigIntNums::BigIntNums(const string &str_org)
     55 {
     56     combineStrToBigInt(str_org);
     57 }
     58 
     59 inline void BigIntNums::clear()
     60 {
     61     numMem.clear();
     62     npFlag = true;
     63 }
     64 
     65 void BigIntNums::combineStrToBigInt(const string &str_org)
     66 {
     67     int base_Count = static_cast<int>(log10(BigIntNums::gap_));
     68 
     69     string str = str_org;
     70     reverse(str.begin(), str.end());
     71     if (!isalnum(str.back()))
     72     {
     73         npFlag = str.back() == '+' ? 1 : 0;
     74         str.pop_back();
     75     }
     76     int cnt = str.size() - base_Count, i;
     77     for (i = 0; i < cnt; i += 4)
     78     {
     79         string cast = str.substr(i, base_Count);
     80         reverse(cast.begin(), cast.end());
     81         int tmp = atoi(cast.c_str());
     82         numMem.push_back(tmp);
     83     }
     84     string cast = str.substr(i, str.size());
     85     reverse(cast.begin(), cast.end());
     86     int tmp = atoi(cast.c_str());
     87     numMem.push_back(tmp);
     88 }
     89 
     90 string BigIntNums::getStr()
     91 {
     92     string tmp;
     93 
     94     for (auto i = numMem.crbegin();i != numMem.crend();++i)
     95     {
     96         stringstream cast;
     97         cast << *i;
     98         tmp += cast.str();
     99     }
    100     return tmp;
    101 }
    102 
    103 BigIntNums::operator bool()
    104 {
    105     return *this != BigIntNums(0);
    106 }
    107 
    108 bool operator==(const BigIntNums &A, const BigIntNums &B)
    109 {
    110     if (A.npFlag != B.npFlag)
    111         return false;
    112     else if (A.numMem.size() != B.numMem.size())
    113         return false;
    114     else
    115     {
    116         for (int i = 0;i < A.numMem.size();i++)
    117             if (A.numMem[i] != B.numMem[i])
    118                 return false;
    119     }
    120     return true;
    121 }
    122 
    123 bool operator!=(const BigIntNums &A, const BigIntNums &B)
    124 {
    125     return !(A == B);
    126 }
    127 
    128 bool operator<(const BigIntNums &A, const BigIntNums &B)
    129 {
    130     if (A.npFlag == true && B.npFlag == false)
    131         return false;
    132     else if (A.npFlag == false && B.npFlag == true)
    133         return true;
    134     else
    135     {
    136         auto ret = A.npFlag && B.npFlag;
    137         if (A.numMem.size() > B.numMem.size())
    138             return !ret;
    139         else if (A.numMem.size() < B.numMem.size())
    140             return ret;
    141         else if (A.numMem.size() == B.numMem.size())
    142         {
    143             for (int i = A.numMem.size() - 1;i >= 0;i--)
    144             {
    145                 if (A.numMem[i] > B.numMem[i])
    146                     return !ret;
    147                 else if (A.numMem[i] < B.numMem[i])
    148                     return ret;
    149             }
    150         }
    151         return false;//相等
    152     }
    153 }
    154 
    155 bool operator>(const BigIntNums &A, const BigIntNums &B)
    156 {
    157     if (A.npFlag == false && B.npFlag == true)
    158         return false;
    159     else if (A.npFlag == true && B.npFlag == false)
    160         return true;
    161     else
    162     {
    163         auto ret = A.npFlag && B.npFlag;
    164         if (A.numMem.size() > B.numMem.size())
    165             return ret;
    166         else if (A.numMem.size() < B.numMem.size())
    167             return !ret;
    168         else if (A.numMem.size() == B.numMem.size())
    169         {
    170             for (int i = A.numMem.size() - 1;i >= 0;i--)
    171             {
    172                 if (A.numMem[i] > B.numMem[i])
    173                     return ret;
    174                 else if (A.numMem[i] < B.numMem[i])
    175                     return !ret;
    176             }
    177         }
    178         return false;//相等
    179     }
    180 }
    181 
    182 bool operator<=(const BigIntNums &A, const BigIntNums &B)
    183 {
    184     return  A < B || A == B;
    185 }
    186 
    187 bool operator>=(const BigIntNums &A, const BigIntNums &B)
    188 {
    189     return A > B || A == B;
    190 }
    191 
    192 BigIntNums abs(const BigIntNums &i)
    193 {
    194     return i >= 0 ? i : -i;
    195 }
    196 
    197 BigIntNums operator-(const BigIntNums &num)
    198 {
    199     BigIntNums newNum(num);
    200     newNum.npFlag = !num.npFlag;
    201     return newNum;
    202 }
    203 
    204 BigIntNums operator+(const BigIntNums &A, const BigIntNums &B)
    205 {
    206     BigIntNums C;
    207 
    208     if (A.npFlag == true && B.npFlag == true)
    209         C.npFlag = true;
    210     else if (A.npFlag == false && B.npFlag == false)
    211         C.npFlag = false;
    212     else if (A.npFlag == true && B.npFlag == false)
    213         return A - (-B);
    214     else if (A.npFlag == false && B.npFlag == true)
    215         return B - (-A);
    216 
    217     std::vector<int> &CM = C.numMem;
    218     const std::vector<int> &AM = A.numMem, &BM = B.numMem;
    219 
    220     int up = 0, tmp;
    221     size_t cnt = std::min(A.numMem.size(), B.numMem.size()), i = 0;
    222 
    223     for (;i < cnt; i++)
    224     {
    225         tmp = AM[i] + BM[i] + up;
    226         CM.push_back(tmp % BigIntNums::gap_);
    227         up = tmp / BigIntNums::gap_;
    228     }
    229     //要注意可能会出现1+999999999999999999999999999的情况
    230     for (;i < AM.size(); i++)
    231     {
    232         tmp = AM[i] + up;
    233         CM.push_back((AM[i] + up) % BigIntNums::gap_);
    234         up = (AM[i] + up) / BigIntNums::gap_;
    235     }
    236     for (;i < BM.size(); i++)
    237     {
    238         tmp = BM[i] + up;
    239         CM.push_back((BM[i] + up) % BigIntNums::gap_);
    240         up = (BM[i] + up) / BigIntNums::gap_;
    241     }
    242     if(up)
    243         CM.push_back(up);
    244     return C;
    245 }
    246 
    247 BigIntNums operator-(const BigIntNums &A, const BigIntNums &B)
    248 {
    249     BigIntNums C;
    250     C.npFlag = true;
    251     if (A.npFlag == true && B.npFlag == true && A < B)
    252     {
    253         C = B - A;
    254         C.npFlag = false;
    255         return C;
    256     }
    257     else if (A.npFlag == false && B.npFlag == false)
    258         return (-B) - (-A);
    259     else if (A.npFlag == true && B.npFlag == false)
    260         return A + (-B);
    261     else if (A.npFlag == false && B.npFlag == true)
    262     {
    263         C = (-A) + B;
    264         C.npFlag = false;
    265         return C;
    266     }    
    267         
    268     std::vector<int> &CM = C.numMem;
    269     const std::vector<int> &AM = A.numMem, &BM = B.numMem;
    270 
    271     int down = 0,  tmp;
    272     size_t cnt = B.numMem.size(), i = 0;
    273 
    274     for (;i < cnt; i++)
    275     {
    276         if (AM[i] - BM[i] - down >= 0)
    277         {
    278             tmp = AM[i] - BM[i] - down;
    279             down = 0;
    280         }
    281         else
    282         {
    283             tmp = BigIntNums::gap_ + AM[i] - BM[i] - down;
    284             down = 1;
    285         }
    286         CM.push_back(tmp);
    287     }
    288     //注意1000000000000000-1的情况
    289     for (;i < A.numMem.size();i++)
    290     {
    291         if (AM[i] - down >= 0)
    292         {
    293             tmp = AM[i] - down;
    294             down = 0;
    295         }
    296         else
    297         {
    298             tmp = BigIntNums::gap_ + AM[i] - down;
    299             down = 1;
    300         }
    301         CM.push_back(tmp);
    302     }
    303     while(C.numMem.back() == 0 && CM.size() != 1)
    304         //如果只剩下0,那还是要保留0
    305         C.numMem.pop_back();
    306     return C;
    307 }
    308 
    309 BigIntNums operator*(const BigIntNums &A, const BigIntNums &B)
    310 {
    311     BigIntNums C;
    312     C.npFlag = true;
    313 
    314     if (A.npFlag == false && B.npFlag == true
    315         || A.npFlag == true && B.npFlag == false)
    316         C.npFlag = false;
    317     
    318     if (abs(A) < abs(B))
    319         return B*A;
    320 
    321     if (A == 0 || B == 0)
    322         return BigIntNums(0);
    323 
    324     const std::vector<int> &AM = A.numMem, &BM = B.numMem;
    325     std::vector<int> &CM = C.numMem;
    326 
    327     int up = 0, tmp;
    328 
    329     for (int i = 0; i < AM.size();i++,up = 0)
    330     {
    331         for (int j = 0; j < BM.size();j++)
    332         {
    333             tmp = AM[i] * BM[j] + up;
    334             if (i + j < CM.size())
    335             {
    336                 up = (tmp + CM[i + j]) / BigIntNums::gap_;
    337                 CM[i + j] = (tmp + CM[i + j]) % BigIntNums::gap_;
    338             }    
    339             else
    340             {
    341                 up = tmp / BigIntNums::gap_;
    342                 CM.push_back(tmp % BigIntNums::gap_);
    343             }
    344         }
    345         if (up)
    346             CM.push_back(up);
    347     }
    348     return C;
    349 }
    350 
    351 BigIntNums operator/(const BigIntNums &A, const BigIntNums &B)
    352 {
    353     int base_Count = static_cast<int>(log10(BigIntNums::gap_));
    354 
    355     if (abs(A) < abs(B))
    356         return BigIntNums(0);
    357     BigIntNums C;
    358     C.npFlag = true;
    359 
    360     if (A.npFlag == false && B.npFlag == true
    361         || A.npFlag == true && B.npFlag == false)
    362         C.npFlag = false;
    363 
    364     int base_Map, tmp;
    365     std::vector<int> rCM;
    366     std::vector<int> &CM = C.numMem;
    367     const std::vector<int> &AM = A.numMem, &BM = B.numMem;
    368     BigIntNums dividend = 0, divisor;
    369     auto CM_Iter = CM.rbegin();
    370 
    371     for (int i = AM.size() - 1; i >= 0;)
    372     {
    373         do {
    374             dividend *= static_cast<int>(pow(BigIntNums::base_, base_Count));
    375             dividend += AM[i--];
    376         } while (dividend < B && i >= 0);
    377             
    378         tmp = 0;
    379         for (int j = base_Count - 1;j >= 0;j--)
    380         {
    381             for (int k = BigIntNums::base_ - 1;;k--)
    382             {
    383                 base_Map = static_cast<int>(pow(BigIntNums::base_, j)) * k;
    384                 auto tmp = abs(B);
    385                 BigIntNums y = tmp * BigIntNums(base_Map);
    386                 if (y <= dividend)
    387                     break;
    388             }
    389             dividend -= abs(B) * BigIntNums(base_Map);
    390             tmp += base_Map;
    391         }
    392         rCM.push_back(tmp);
    393     }
    394     for (auto i = rCM.crbegin();i != rCM.crend();++i)
    395         CM.push_back(*i);
    396     while (C.numMem.back() == 0 && CM.size() != 1)
    397         C.numMem.pop_back();
    398 
    399     return C;
    400 }
    401 
    402 BigIntNums operator%(const BigIntNums &A, const BigIntNums &B)
    403 {
    404     auto ret = A / B;
    405     return A - ret*B;
    406 }
    407 
    408 BigIntNums &BigIntNums::operator++()
    409 {
    410     *this = *this + BigIntNums(1);
    411     return *this;
    412 }
    413 
    414 BigIntNums &BigIntNums::operator--()
    415 {
    416     *this = *this - BigIntNums(1);
    417     return *this;
    418 }
    419 
    420 BigIntNums &BigIntNums::operator=(const BigIntNums &ob)
    421 {
    422     if (&ob != this)
    423     {
    424         this->numMem = ob.numMem;
    425         this->npFlag = ob.npFlag;
    426     }
    427     return *this;
    428 }
    429 
    430 BigIntNums &BigIntNums::operator+=(const BigIntNums &ob)
    431 {
    432     *this = *this + ob;
    433     return *this;
    434 }
    435 
    436 BigIntNums &BigIntNums::operator-=(const BigIntNums &ob)
    437 {
    438     *this = *this - ob;
    439     return *this;
    440 }
    441 
    442 BigIntNums &BigIntNums::operator*=(const BigIntNums &ob)
    443 {
    444     *this = *this * ob;
    445     return *this;
    446 }
    447 
    448 BigIntNums &BigIntNums::operator/=(const BigIntNums &ob)
    449 {
    450     *this = *this / ob;
    451     return *this;
    452 }

     

  • 相关阅读:
    源码实现 --> strcmp
    源码实现 --> strdel
    源码实现 --> strcpy
    SoC的Testbench中的简易bus_monitor(加入print函数)
    debian 安装后需做的几件事
    使用Perl合并文件
    一个简单的Verilog计数器模型
    Environment Modules简单使用
    Git push “fatal: Authentication failed ”
    使用SystemC进行硬件仿真
  • 原文地址:https://www.cnblogs.com/Philip-Tell-Truth/p/5738966.html
Copyright © 2011-2022 走看看