大整数模板

  稍微测试了一下感觉还行,可能有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 }

 

 

 

posted @ 2016-08-05 00:08  PhiliAI  阅读(338)  评论(0编辑  收藏  举报