Advertisement
Guest User

Untitled

a guest
Nov 11th, 2019
103
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 6.84 KB | None | 0 0
  1. #pragma once
  2. #include <cctype>
  3. #include <algorithm>
  4. #include <regex>
  5. #include <vector>
  6. #include <numeric>
  7. #include <execution>
  8. #include <string>
  9. #include <stdint.h>
  10.  
  11. #define SUPPORT_DIVISION 0 // define as 1 when you have implemented the division
  12. #define SUPPORT_IFSTREAM 0 // define as 1 when you have implemented the input >>
  13.  
  14. class BigNum final
  15. {
  16. public:
  17.     // constructors
  18.     BigNum() : BigNum(0) {}
  19.     BigNum(int64_t n) : BigNum(std::to_string(n)) {}
  20.  
  21.     explicit BigNum(const std::string& str)
  22.     {
  23.         std::regex number_regex("[+-]?0*[0-9]+");
  24.  
  25.         if (!std::regex_match(str, number_regex))
  26.         {
  27.             throw std::invalid_argument("Argument has to be in a correct format.\n");
  28.         }
  29.  
  30.         bool isNegativeSign = str[0] == '-';
  31.         size_t digitsStartID = str[0] == '+' || str[0] == '-' ? 1 : 0;
  32.  
  33.         for (size_t i = digitsStartID; i < str.size(); i++)
  34.         {
  35.             if (str[i] == '0')
  36.             {
  37.                 digitsStartID++;
  38.             }
  39.             else
  40.             {
  41.                 break;
  42.             }
  43.         }
  44.  
  45.         if (digitsStartID == str.size())
  46.         {
  47.             this->m_isNegative = false;
  48.             this->m_buffer = "0";
  49.         }
  50.         else
  51.         {
  52.             this->m_isNegative = isNegativeSign;
  53.             this->m_buffer = std::string(str.begin() + digitsStartID, str.end());
  54.             std::reverse(this->m_buffer.begin(), this->m_buffer.end());
  55.         }
  56.     }
  57.  
  58.     // copy
  59.     BigNum(const BigNum& other) = default;
  60.     BigNum& operator=(const BigNum& rhs) = default;
  61.  
  62.     // unary operators
  63.     const BigNum& operator+() const
  64.     {
  65.         return *this;
  66.     }
  67.  
  68.     BigNum operator-() const
  69.     {
  70.         if (this->m_buffer == "0")
  71.             return BigNum(*this);
  72.  
  73.         BigNum result(*this);
  74.         result.m_isNegative = !result.m_isNegative;
  75.         return result;
  76.     }
  77.  
  78.     // binary arithmetics operators
  79.     BigNum& operator+=(const BigNum& rhs)
  80.     {
  81.         *this = *this + rhs;
  82.         return *this;
  83.     }
  84.  
  85.     BigNum& operator-=(const BigNum& rhs)
  86.     {
  87.         *this = *this - rhs;
  88.         return *this;
  89.     }
  90.  
  91.     BigNum& operator*=(const BigNum& rhs)
  92.     {
  93.         *this = *this * rhs;
  94.         return *this;
  95.     }
  96.  
  97. private:
  98.     bool m_isNegative;
  99.     std::string m_buffer;
  100.  
  101.     // friends
  102.     friend BigNum operator+(BigNum lhs, const BigNum& rhs);
  103.     friend BigNum operator-(BigNum lhs, const BigNum& rhs);
  104.     friend BigNum operator*(BigNum lhs, const BigNum& rhs);
  105.  
  106.     friend bool operator<(const BigNum& lhs, const BigNum& rhs);
  107.     friend bool operator==(const BigNum& lhs, const BigNum& rhs);
  108.  
  109.     friend std::ostream& operator<<(std::ostream& lhs, const BigNum& rhs);
  110. };
  111.  
  112. BigNum operator+(BigNum lhs, const BigNum& rhs)
  113. {
  114.     if (lhs.m_isNegative == rhs.m_isNegative)
  115.     {
  116.         char carry = 0;
  117.         std::string resultStr;
  118.    
  119.         std::string left = lhs.m_buffer;
  120.         std::string right = rhs.m_buffer;
  121.         size_t maxLength = std::max(left.size(), right.size());
  122.  
  123.         left.resize(maxLength, '0');
  124.         right.resize(maxLength, '0');
  125.  
  126.         for (size_t i = 0; i < maxLength; i++)
  127.         {
  128.             char lNum = left[i] - '0';
  129.             char rNum = right[i] - '0';
  130.  
  131.             char new_num = lNum + rNum + carry;
  132.        
  133.             carry = new_num / 10;
  134.             resultStr += (new_num % 10) + '0';
  135.         }
  136.  
  137.         if(carry > 0)
  138.         {
  139.             resultStr += carry + '0';
  140.         }
  141.  
  142.         std::reverse(resultStr.begin(), resultStr.end());
  143.         return lhs.m_isNegative ? -BigNum(resultStr) : BigNum(resultStr);
  144.     }
  145.     else
  146.     {
  147.         if (lhs.m_isNegative)
  148.             return rhs - (-lhs);
  149.         else
  150.             return lhs - (-rhs);
  151.     }
  152. }
  153.  
  154. BigNum operator-(BigNum lhs, const BigNum& rhs)
  155. {
  156.     if (lhs.m_isNegative == rhs.m_isNegative)
  157.     {
  158.         if (lhs == rhs)
  159.             return BigNum(0);
  160.  
  161.         if (lhs.m_isNegative)
  162.             return -rhs - lhs;
  163.  
  164.         char carry = 0;
  165.         std::string resultStr;
  166.  
  167.         bool shouldSwap = lhs < rhs;
  168.         std::string left = shouldSwap ? rhs.m_buffer : lhs.m_buffer;
  169.         std::string right = shouldSwap ? lhs.m_buffer : rhs.m_buffer;
  170.         size_t maxLength = std::max(left.size(), right.size());
  171.  
  172.         left.resize(maxLength, '0');
  173.         right.resize(maxLength, '0');
  174.  
  175.         for (size_t i = 0; i < maxLength; i++)
  176.         {
  177.             char lnum = left[i] - '0';
  178.             char rnum = right[i] - '0';
  179.  
  180.             char newNum = lnum - (rnum + carry);
  181.             carry = newNum < 0 ? 1 : 0;
  182.             newNum = newNum < 0 ? newNum + 10 : newNum;
  183.  
  184.             resultStr += newNum + '0';
  185.         }
  186.  
  187.         std::reverse(resultStr.begin(), resultStr.end());
  188.         return shouldSwap ? -BigNum(resultStr) : BigNum(resultStr);
  189.     }
  190.     else
  191.     {
  192.         if (lhs.m_isNegative)
  193.             return lhs + (-rhs);
  194.         else
  195.             return lhs + (-rhs);
  196.     }
  197.  
  198. }
  199.  
  200. BigNum operator*(BigNum lhs, const BigNum& rhs)
  201. {
  202.     std::string left = lhs.m_buffer;
  203.     std::string right = rhs.m_buffer;
  204.     size_t maxLength = std::max(left.size(), right.size());
  205.  
  206.     left.resize(maxLength, '0');
  207.     right.resize(maxLength, '0');
  208.  
  209.     std::vector<std::string> multiplicationRows(maxLength, std::string(maxLength * 2, '0'));
  210.  
  211.     for (size_t row = 0; row < right.size(); row++)
  212.     {
  213.         char carry = 0;
  214.         for (size_t i = 0; i < left.size(); i++)
  215.         {
  216.             char lNum = left[i] - '0';
  217.             char rNum = right[row] - '0';
  218.  
  219.             char newNum = lNum * rNum + carry;
  220.             carry = newNum / 10;
  221.  
  222.             multiplicationRows[row][i + row] = (newNum % 10) + '0';
  223.         }
  224.  
  225.         if (carry > 0)
  226.         {
  227.             multiplicationRows[row][left.size() + row] = carry + '0';
  228.         }
  229.     }
  230.  
  231.     std::vector<BigNum> rowBigNums;
  232.     rowBigNums.reserve(maxLength);
  233.     for (const auto& row : multiplicationRows)
  234.     {
  235.         rowBigNums.push_back(BigNum(std::string(row.rbegin(), row.rend())));
  236.     }
  237.  
  238.     // Let's go declarative!
  239.     BigNum resultNum = std::reduce(
  240.         std::execution::par,
  241.         rowBigNums.begin(),
  242.         rowBigNums.end(),
  243.         BigNum(0),
  244.         [](BigNum a, BigNum b) -> BigNum { return a + b; }
  245.     );
  246.  
  247.     return (lhs.m_isNegative != rhs.m_isNegative) ? -resultNum : resultNum;
  248. }
  249.  
  250. bool operator==(const BigNum& lhs, const BigNum& rhs)
  251. {
  252.     if (lhs.m_isNegative != rhs.m_isNegative)
  253.         return false;
  254.  
  255.     if (lhs.m_buffer.size() != rhs.m_buffer.size())
  256.         return false;
  257.  
  258.     for (size_t i = 0; i < lhs.m_buffer.size(); i++)
  259.     {
  260.         if (lhs.m_buffer[i] != rhs.m_buffer[i])
  261.             return false;
  262.     }
  263.  
  264.     return true;
  265. }
  266.  
  267. bool operator!=(const BigNum& lhs, const BigNum& rhs)
  268. {
  269.     return !(lhs == rhs);
  270. }
  271.  
  272. bool operator<(const BigNum& lhs, const BigNum& rhs)
  273. {
  274.     if (lhs.m_isNegative != rhs.m_isNegative)
  275.         return lhs.m_isNegative == true;
  276.  
  277.     if (lhs.m_buffer.size() != rhs.m_buffer.size())
  278.         return lhs.m_buffer.size() < rhs.m_buffer.size();
  279.  
  280.     std::string left(lhs.m_buffer.rbegin(), lhs.m_buffer.rend());
  281.     std::string right(rhs.m_buffer.rbegin(), rhs.m_buffer.rend());
  282.  
  283.     for (size_t i = 0; i < left.size(); i++)
  284.     {
  285.         if (left[i] != right[i])
  286.         {
  287.             if (left[i] < right[i])
  288.                 return true;
  289.             else
  290.                 return false;
  291.         }
  292.     }
  293.  
  294.     return false;
  295. }
  296.  
  297. bool operator>(const BigNum& lhs, const BigNum& rhs)
  298. {
  299.     return !(lhs < rhs) && lhs != rhs;
  300. }
  301.  
  302. bool operator<=(const BigNum& lhs, const BigNum& rhs)
  303. {
  304.     return lhs < rhs || lhs == rhs;
  305. }
  306.  
  307. bool operator>=(const BigNum& lhs, const BigNum& rhs)
  308. {
  309.     return lhs > rhs || lhs == rhs;
  310. }
  311.  
  312.  
  313. std::ostream& operator<<(std::ostream& lhs, const BigNum& rhs)
  314. {
  315.     if (rhs.m_isNegative)
  316.     {
  317.         lhs << "-";
  318.     }
  319.     lhs << std::string(rhs.m_buffer.rbegin(), rhs.m_buffer.rend());
  320.     return lhs;
  321. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement