码迷,mamicode.com
首页 > 编程语言 > 详细

C/C++:大整数模板

时间:2016-08-05 00:46:28      阅读:278      评论:0      收藏:0      [点我收藏+]

标签:

  写文件管理的时候看到书上的Demo代码居然是用qunit64写的。。。坑爹啊,文件大小表示居然用qunit64,太不严谨了吧,想了下还是写了这个东西,本来想写浮点的,后来想下算了还蛮复杂的,先用着吧。稍微测试了一下感觉还行,可能有BUG,如果发现了还望告诉我

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

 技术分享

C/C++:大整数模板

标签:

原文地址:http://www.cnblogs.com/Philip-Tell-Truth/p/5738966.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!