Advertisement
paranid5

BigInt

Aug 6th, 2020
202
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 11.82 KB | None | 0 0
  1. #ifndef BIGINT_H
  2. #define BIGINT_H
  3. #include <vector>
  4. #include <string>
  5. typedef unsigned short elem_t;
  6.  
  7. class BigInt
  8. {
  9. public:
  10.     explicit BigInt(long long);
  11.     explicit BigInt(const std::vector<elem_t>&);
  12.     explicit BigInt(const std::string&);
  13.     ~BigInt();
  14.    
  15.     BigInt operator + (const BigInt&);
  16.     BigInt operator - (const BigInt&);
  17.     BigInt operator * (const BigInt&);
  18.     BigInt operator / (const BigInt&);
  19.     BigInt operator % (const BigInt&);
  20.     bool operator > (const BigInt&);
  21.     bool operator < (const BigInt&);
  22.     bool operator >= (const BigInt&);
  23.     bool operator <= (const BigInt&);
  24.     bool operator == (const BigInt&);
  25.     bool operator != (const BigInt&);
  26.     void operator = (const BigInt&);
  27.     void operator += (const BigInt&);
  28.     void operator -= (const BigInt&);
  29.     void operator *= (const BigInt&);
  30.     void operator /= (const BigInt&);
  31.     void operator %= (const BigInt&);
  32.     void operator ++ ();
  33.     void operator ++ (int);
  34.     void operator -- ();
  35.     void operator -- (int);
  36.    
  37.     BigInt operator + (const long long);
  38.     BigInt operator - (const long long);
  39.     BigInt operator * (const long long);
  40.     BigInt operator / (const long long);
  41.     BigInt operator % (const long long);
  42.     bool operator > (const long long);
  43.     bool operator < (const long long);
  44.     bool operator >= (const long long);
  45.     bool operator <= (const long long);
  46.     bool operator == (const long long);
  47.     bool operator != (const long long);
  48.     void operator = (const long long);
  49.     void operator += (const long long);
  50.     void operator -= (const long long);
  51.     void operator *= (const long long);
  52.     void operator /= (const long long);
  53.     void operator %= (const long long);
  54.    
  55.     BigInt pow(const BigInt&);
  56.     std::pair<BigInt, int> sqrt(const BigInt&);
  57.     BigInt abs() const;
  58.     BigInt gcd(const BigInt&);
  59.     BigInt swap(const BigInt&);
  60.     BigInt copy() const;
  61.    
  62.     std::string to_string();
  63.    
  64. private:
  65.     std::vector<elem_t> collect;
  66.     BigInt change_signe() const;
  67.     BigInt minus(const BigInt&) const;
  68.     BigInt plus(const BigInt&) const;
  69. };
  70.  
  71. std::vector<elem_t > convert(const long long);
  72.  
  73. BigInt convert_big(const long long);
  74.  
  75. #endif //BIGINT_H
  76.  
  77.  
  78.  
  79. #include "library.h"
  80. #include <cassert>
  81. #include <deque>
  82. #include <algorithm>
  83. #define LOOP while (true)
  84.  
  85. inline void assertmsg(const bool expression, const char* message)
  86. {
  87.     assert(((void)message, expression));
  88. }
  89.  
  90. std::vector<elem_t > convert(const long long right)
  91. {
  92.     std::deque<elem_t> right_collect;
  93.    
  94.     long long abs_right = std::abs(right);
  95.     while (abs_right > 0)
  96.     {
  97.         right_collect.push_front(abs_right % 10);
  98.         abs_right /= 10;
  99.     }
  100.     if (right < 0) right_collect.push_front(10);
  101.    
  102.     std::vector<elem_t> res_vec(right_collect.size());
  103.     std::move(right_collect.begin(), right_collect.end(), res_vec.begin());
  104.     return res_vec;
  105. }
  106.  
  107. inline BigInt convert_big(const long long right)
  108. {
  109.     BigInt res(std::move(convert(right)));
  110.     return res;
  111. }
  112.  
  113. BigInt::BigInt(long long construct)
  114. {
  115.     std::deque<elem_t> new_int;
  116.     bool otr = construct < 0;
  117.    
  118.     construct = construct > 0 ? construct : -construct;
  119.     while (construct > 0)
  120.     {
  121.         new_int.push_front(construct % 10);
  122.         construct /= 10;
  123.     }
  124.     if (otr) new_int.push_front(10);
  125.     std::move(new_int.begin(), new_int.end(), collect.begin());
  126. }
  127.  
  128. BigInt::BigInt(const std::vector<elem_t>& construct)
  129. {
  130.     std::copy(construct.begin(), construct.end(), collect.begin());
  131. }
  132.  
  133. BigInt::BigInt(const std::string& construct)
  134. {
  135.     for (char i : construct)
  136.     {
  137.         if (i == '-') collect.push_back(10);
  138.         else
  139.         {
  140.             assertmsg(i < 48 || i > 57, "Incorrect string to construct BigInt (string_type constructor)");
  141.             collect.push_back(i - 48);
  142.         }
  143.     }
  144. }
  145.  
  146. BigInt BigInt::plus(const BigInt& right) const
  147. {
  148.     std::deque<elem_t> res_d;
  149.     elem_t per = 0;
  150.     size_t l_ptr = collect.size() - 1;
  151.     size_t r_ptr = right.collect.size() - 1;
  152.    
  153.     LOOP
  154.     {
  155.         res_d.push_front((collect[l_ptr] + right.collect[r_ptr] + per) % 10);
  156.         per = collect[l_ptr] + right.collect[r_ptr] + per > 9 ? 1 : 0;
  157.         if (l_ptr == 0 || r_ptr == 0) break;
  158.         l_ptr--, r_ptr--;
  159.     }
  160.    
  161.     while (l_ptr != 0)
  162.     {
  163.         res_d.push_front((collect[l_ptr] + per) % 10);
  164.         per = collect[l_ptr] + per > 9 ? 1 : 0;
  165.         l_ptr--;
  166.     }
  167.    
  168.     while (r_ptr != 0)
  169.     {
  170.         res_d.push_front((right.collect[r_ptr] + per) % 10);
  171.         per = right.collect[r_ptr] + per > 9 ? 1 : 0;
  172.         r_ptr--;
  173.     }
  174.    
  175.     if (per == 1)
  176.         res_d.push_front(1);
  177.    
  178.     std::vector<elem_t>res_vec;
  179.     std::move(res_d.begin(), res_d.end(), res_vec.begin());
  180.     BigInt res(res_vec);
  181.     return res;
  182. }
  183.  
  184. BigInt BigInt::operator +(const BigInt& right)
  185. {
  186.     assertmsg(collect.empty(),"Left argument is empty (operator +)");
  187.     assertmsg(right.collect.empty(),"Right argument is empty (operator +)");
  188.    
  189.     if (right.collect[0] != 10 && collect[0] != 10) // + +
  190.         return this->plus(right);
  191.     else if (this->collect[0] == 10 && right.collect[0] == 10) // - -
  192.         return (this->abs().plus(right.abs())).change_signe();
  193.     return *this - right;
  194.    
  195. }
  196.  
  197. BigInt BigInt::operator +(const long long right)
  198. {
  199.     assertmsg(collect.empty(),"Left argument is empty (operator +)");
  200.     BigInt res(convert_big(right));
  201.     return this->plus(res);
  202. }
  203.  
  204. BigInt BigInt::minus(const BigInt& right) const
  205. {
  206.     std::deque<elem_t> res_d;
  207.     size_t l_ptr = (*this).collect.size() - 1;
  208.     size_t r_ptr = right.collect.size() - 1;
  209.    
  210.     std::vector<elem_t> right_cpy(right.collect.size());
  211.     std::vector<elem_t> this_cpy((*this).collect.size());
  212.     std::copy(right.collect.begin(), right.collect.end(), right_cpy.begin());
  213.     std::copy((*this).collect.begin(), (*this).collect.end(), this_cpy.begin());
  214.    
  215.     while (r_ptr >= 0)
  216.     {
  217.         if (right_cpy[r_ptr] == 10) break;
  218.         else
  219.         {
  220.             if (this_cpy[l_ptr] >= right_cpy[r_ptr])
  221.                 res_d.push_front(this_cpy[l_ptr] - right_cpy[r_ptr]);
  222.             else
  223.             {
  224.                 size_t i = 1;
  225.                 while (this_cpy[l_ptr - i] == 0) ++i;
  226.                 this_cpy[l_ptr - i]--;
  227.                 res_d.push_front(this_cpy[l_ptr] + 10 - right_cpy[r_ptr]);
  228.             }
  229.            
  230.             if (r_ptr == 0){l_ptr--; break;}
  231.             r_ptr--, l_ptr--;
  232.            
  233.         }
  234.     }
  235.    
  236.     while (l_ptr > 0)
  237.     {
  238.         res_d.push_front(this_cpy[l_ptr]);
  239.         l_ptr--;
  240.     }
  241.    
  242.     bool otr = false;
  243.     if (this_cpy[0] != 10)
  244.         res_d.push_front(this_cpy[0]);
  245.     else
  246.         otr = true;
  247.    
  248.     std::vector<elem_t> res_vec(res_d.size() - (otr ? 0 : 1));
  249.     if (otr) res_vec[0] = 10;
  250.     std::move(res_d.begin(), res_d.end(), res_vec.begin() + (otr ? 1 : 0));
  251.     BigInt res(res_vec);
  252.     return res;
  253. }
  254.  
  255. BigInt BigInt::operator -(const BigInt& right)
  256. {
  257.     assertmsg(collect.empty(),"Left argument is empty (operator -)");
  258.     assertmsg(right.collect.empty(),"Right argument is empty (operator -)");
  259.    
  260.     if (collect[0] != 10 && right.collect[0] == 10) // + -
  261.         return *this + right.abs();
  262.     if (collect[0] == 10 && right.collect[0] != 10) // - +
  263.         return ((*this).abs() + right).change_signe();
  264.    
  265.     // - - / + +
  266.    
  267.     if ((*this).abs() > right.abs())
  268.         return this->minus(right);
  269.     else if ((*this).abs() < right.abs())
  270.         return right.minus(*this);
  271.     else
  272.     {
  273.         std::vector<elem_t> res_vec(1, 0);
  274.         BigInt res(res_vec);
  275.         return res;
  276.     }
  277. }
  278.  
  279. BigInt BigInt::operator -(const long long right)
  280. {
  281.     assertmsg(collect.empty(),"Left argument is empty (operator -)");
  282.     BigInt res(convert_big(right));
  283.     return *this - res;
  284. }
  285.  
  286. BigInt BigInt::operator *(const BigInt& right)
  287. {
  288.     BigInt res(convert_big(0));
  289.    
  290.     for (BigInt i = convert_big(0); i < right; ++i)
  291.         res += i;
  292.     return res;
  293.    
  294. }
  295.  
  296. BigInt BigInt::operator *(const long long right)
  297. {
  298.     BigInt res(convert_big(0));
  299.     BigInt Right(convert_big(right));
  300.    
  301.     for (BigInt i = convert_big(0); i < Right; ++i)
  302.         res += i;
  303.     return res;
  304.    
  305. }
  306.  
  307. bool BigInt::operator >(const BigInt& right)
  308. {
  309.     if (this->collect[0] == 10)
  310.     {
  311.         if (right.collect[0] != 10) return false;
  312.         else
  313.         {
  314.             if ((*this).collect.size() > right.collect.size()) return false;
  315.             else if ((*this).collect.size() < right.collect.size()) return true;
  316.             else
  317.             {
  318.                 for (size_t i = 1; i < right.collect.size(); ++i)
  319.                 {
  320.                     if ((*this).collect[i] > right.collect[i]) return false;
  321.                     else if ((*this).collect[i] < right.collect[i]) return true;
  322.                 }
  323.                 return false;
  324.             }
  325.         }
  326.     }
  327.     else
  328.     {
  329.         if (right.collect[0] == 10) return true;
  330.         else
  331.         {
  332.             if ((*this).collect.size() > right.collect.size()) return true;
  333.             else if ((*this).collect.size() < right.collect.size()) return false;
  334.             else
  335.             {
  336.                 for (size_t i = 0; i < right.collect.size(); ++i)
  337.                 {
  338.                     if ((*this).collect[i] > right.collect[i]) return true;
  339.                     else if ((*this).collect[i] < right.collect[i]) return false;
  340.                 }
  341.                 return false;
  342.             }
  343.         }
  344.     }
  345. }
  346.  
  347. inline bool BigInt::operator >(const long long right)
  348. {
  349.     BigInt res(convert_big(right));
  350.     return *this > res;
  351. }
  352.  
  353. inline bool BigInt::operator ==(const BigInt& right)
  354. {
  355.     return std::equal((*this).collect.begin(), (*this).collect.end(),
  356.             right.collect.begin(), right.collect.end());
  357. }
  358.  
  359. inline bool BigInt::operator ==(const long long right)
  360. {
  361.     std::vector<elem_t> res_collect(std::move(convert(right)));
  362.     return std::equal((*this).collect.begin(), (*this).collect.end(),
  363.             res_collect.begin(), res_collect.end());
  364. }
  365.  
  366. inline bool BigInt::operator !=(const BigInt& right)
  367. {
  368.     return !(*this == right);
  369. }
  370.  
  371. inline bool BigInt::operator !=(const long long right)
  372. {
  373.     std::vector<elem_t> res_collect(std::move(convert(right)));;
  374.     return !std::equal((*this).collect.begin(), (*this).collect.end(),
  375.             res_collect.begin(), res_collect.end());
  376. }
  377.  
  378. inline bool BigInt::operator >=(const BigInt& right)
  379. {
  380.     return *this > right ? true : *this == right;
  381. }
  382.  
  383. inline bool BigInt::operator >=(const long long right)
  384. {
  385.     return *this > right ? true : *this == right;
  386. }
  387.  
  388. inline bool BigInt::operator <(const BigInt& right)
  389. {
  390.     return !(*this >= right);
  391. }
  392.  
  393. inline bool BigInt::operator <(const long long right)
  394. {
  395.     return !(*this >= right);
  396. }
  397.  
  398. inline bool BigInt::operator <=(const BigInt& right)
  399. {
  400.     return *this == right ? true : *this < right;
  401. }
  402.  
  403. inline bool BigInt::operator <=(const long long right)
  404. {
  405.     return *this == right ? true : *this < right;
  406. }
  407.  
  408. inline void BigInt::operator =(const BigInt& right)
  409. {
  410.     (*this).collect.resize(right.collect.size());
  411.     std::move(right.collect.begin(), right.collect.end(), (*this).collect.begin());
  412. }
  413.  
  414. inline void BigInt::operator =(const long long right)
  415. {
  416.     std::vector<elem_t> res_collect(std::move(convert(right)));
  417.     (*this).collect.resize(res_collect.size());
  418.     std::move(res_collect.begin(), res_collect.end(), (*this).collect.begin());
  419. }
  420.  
  421. inline void BigInt::operator +=(const BigInt& right)
  422. {
  423.     *this = *this + right;
  424. }
  425.  
  426. inline void BigInt::operator +=(const long long right)
  427. {
  428.     *this = *this + right;
  429. }
  430.  
  431. inline void BigInt::operator -=(const BigInt& right)
  432. {
  433.     *this = *this - right;
  434. }
  435.  
  436. inline void BigInt::operator -=(const long long right)
  437. {
  438.     *this = *this - right;
  439. }
  440.  
  441. inline void BigInt::operator *=(const BigInt& right)
  442. {
  443.     *this = *this * right;
  444. }
  445.  
  446. inline void BigInt::operator *=(const long long right)
  447. {
  448.     *this = *this * right;
  449. }
  450.  
  451. inline void BigInt::operator++()
  452. {
  453.     *this = *this + 1;
  454. }
  455.  
  456. inline void BigInt::operator--()
  457. {
  458.     *this = *this - 1;
  459. }
  460.  
  461. BigInt BigInt::abs() const
  462. {
  463.     assertmsg(collect.empty(),"Argument is empty (abs method)");
  464.     if (collect[0] != 0)
  465.         return *this;
  466.     else
  467.     {
  468.         std::vector<elem_t> res_vec(collect.size() - 1);
  469.         BigInt res(res_vec);
  470.         std::copy(collect.begin() + 1, collect.end(), res.collect.begin());
  471.         return res;
  472.     }
  473. }
  474.  
  475. BigInt BigInt::change_signe() const
  476. {
  477.     if (this->collect[0] != 10)
  478.     {
  479.         std::vector<elem_t> res_v((*this).collect.size() + 1);
  480.         std::copy((*this).collect.begin(), (*this).collect.end(), res_v.begin() + 1);
  481.         res_v[0] = 10;
  482.         BigInt res(res_v);
  483.         return res;
  484.     }
  485.     else return (*this).abs();
  486. }
  487.  
  488. inline BigInt BigInt::copy() const
  489. {
  490.     return *this;
  491. }
  492.  
  493. std::string BigInt::to_string()
  494. {
  495.     std::string out(this->collect.size(), '0');
  496.     for (elem_t i = 0; i < this->collect.size(); ++i)
  497.         out[i] = this->collect[i] == 10 ? '-' : this->collect[i] + 48;
  498.     return out;
  499. }
  500.  
  501. BigInt::~BigInt() = default;
  502.  
  503.  
  504.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement