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