Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #pragma once
- #include <cctype>
- #include <algorithm>
- #include <regex>
- #include <vector>
- #include <numeric>
- #include <execution>
- #include <string>
- #include <stdint.h>
- #define SUPPORT_DIVISION 0 // define as 1 when you have implemented the division
- #define SUPPORT_IFSTREAM 0 // define as 1 when you have implemented the input >>
- class BigNum final
- {
- public:
- // constructors
- BigNum() : BigNum(0) {}
- BigNum(int64_t n) : BigNum(std::to_string(n)) {}
- explicit BigNum(const std::string& str)
- {
- std::regex number_regex("[+-]?0*[0-9]+");
- if (!std::regex_match(str, number_regex))
- {
- throw std::invalid_argument("Argument has to be in a correct format.\n");
- }
- bool isNegativeSign = str[0] == '-';
- size_t digitsStartID = str[0] == '+' || str[0] == '-' ? 1 : 0;
- for (size_t i = digitsStartID; i < str.size(); i++)
- {
- if (str[i] == '0')
- {
- digitsStartID++;
- }
- else
- {
- break;
- }
- }
- if (digitsStartID == str.size())
- {
- this->m_isNegative = false;
- this->m_buffer = "0";
- }
- else
- {
- this->m_isNegative = isNegativeSign;
- this->m_buffer = std::string(str.begin() + digitsStartID, str.end());
- std::reverse(this->m_buffer.begin(), this->m_buffer.end());
- }
- }
- // copy
- BigNum(const BigNum& other) = default;
- BigNum& operator=(const BigNum& rhs) = default;
- // unary operators
- const BigNum& operator+() const
- {
- return *this;
- }
- BigNum operator-() const
- {
- if (this->m_buffer == "0")
- return BigNum(*this);
- BigNum result(*this);
- result.m_isNegative = !result.m_isNegative;
- return result;
- }
- // binary arithmetics operators
- BigNum& operator+=(const BigNum& rhs)
- {
- *this = *this + rhs;
- return *this;
- }
- BigNum& operator-=(const BigNum& rhs)
- {
- *this = *this - rhs;
- return *this;
- }
- BigNum& operator*=(const BigNum& rhs)
- {
- *this = *this * rhs;
- return *this;
- }
- private:
- bool m_isNegative;
- std::string m_buffer;
- // friends
- friend BigNum operator+(BigNum lhs, const BigNum& rhs);
- friend BigNum operator-(BigNum lhs, const BigNum& rhs);
- friend BigNum operator*(BigNum lhs, const BigNum& rhs);
- friend bool operator<(const BigNum& lhs, const BigNum& rhs);
- friend bool operator==(const BigNum& lhs, const BigNum& rhs);
- friend std::ostream& operator<<(std::ostream& lhs, const BigNum& rhs);
- };
- BigNum operator+(BigNum lhs, const BigNum& rhs)
- {
- if (lhs.m_isNegative == rhs.m_isNegative)
- {
- char carry = 0;
- std::string resultStr;
- std::string left = lhs.m_buffer;
- std::string right = rhs.m_buffer;
- size_t maxLength = std::max(left.size(), right.size());
- left.resize(maxLength, '0');
- right.resize(maxLength, '0');
- for (size_t i = 0; i < maxLength; i++)
- {
- char lNum = left[i] - '0';
- char rNum = right[i] - '0';
- char new_num = lNum + rNum + carry;
- carry = new_num / 10;
- resultStr += (new_num % 10) + '0';
- }
- if(carry > 0)
- {
- resultStr += carry + '0';
- }
- std::reverse(resultStr.begin(), resultStr.end());
- return lhs.m_isNegative ? -BigNum(resultStr) : BigNum(resultStr);
- }
- else
- {
- if (lhs.m_isNegative)
- return rhs - (-lhs);
- else
- return lhs - (-rhs);
- }
- }
- BigNum operator-(BigNum lhs, const BigNum& rhs)
- {
- if (lhs.m_isNegative == rhs.m_isNegative)
- {
- if (lhs == rhs)
- return BigNum(0);
- if (lhs.m_isNegative)
- return -rhs - lhs;
- char carry = 0;
- std::string resultStr;
- bool shouldSwap = lhs < rhs;
- std::string left = shouldSwap ? rhs.m_buffer : lhs.m_buffer;
- std::string right = shouldSwap ? lhs.m_buffer : rhs.m_buffer;
- size_t maxLength = std::max(left.size(), right.size());
- left.resize(maxLength, '0');
- right.resize(maxLength, '0');
- for (size_t i = 0; i < maxLength; i++)
- {
- char lnum = left[i] - '0';
- char rnum = right[i] - '0';
- char newNum = lnum - (rnum + carry);
- carry = newNum < 0 ? 1 : 0;
- newNum = newNum < 0 ? newNum + 10 : newNum;
- resultStr += newNum + '0';
- }
- std::reverse(resultStr.begin(), resultStr.end());
- return shouldSwap ? -BigNum(resultStr) : BigNum(resultStr);
- }
- else
- {
- if (lhs.m_isNegative)
- return lhs + (-rhs);
- else
- return lhs + (-rhs);
- }
- }
- BigNum operator*(BigNum lhs, const BigNum& rhs)
- {
- std::string left = lhs.m_buffer;
- std::string right = rhs.m_buffer;
- size_t maxLength = std::max(left.size(), right.size());
- left.resize(maxLength, '0');
- right.resize(maxLength, '0');
- std::vector<std::string> multiplicationRows(maxLength, std::string(maxLength * 2, '0'));
- for (size_t row = 0; row < right.size(); row++)
- {
- char carry = 0;
- for (size_t i = 0; i < left.size(); i++)
- {
- char lNum = left[i] - '0';
- char rNum = right[row] - '0';
- char newNum = lNum * rNum + carry;
- carry = newNum / 10;
- multiplicationRows[row][i + row] = (newNum % 10) + '0';
- }
- if (carry > 0)
- {
- multiplicationRows[row][left.size() + row] = carry + '0';
- }
- }
- std::vector<BigNum> rowBigNums;
- rowBigNums.reserve(maxLength);
- for (const auto& row : multiplicationRows)
- {
- rowBigNums.push_back(BigNum(std::string(row.rbegin(), row.rend())));
- }
- // Let's go declarative!
- BigNum resultNum = std::reduce(
- std::execution::par,
- rowBigNums.begin(),
- rowBigNums.end(),
- BigNum(0),
- [](BigNum a, BigNum b) -> BigNum { return a + b; }
- );
- return (lhs.m_isNegative != rhs.m_isNegative) ? -resultNum : resultNum;
- }
- bool operator==(const BigNum& lhs, const BigNum& rhs)
- {
- if (lhs.m_isNegative != rhs.m_isNegative)
- return false;
- if (lhs.m_buffer.size() != rhs.m_buffer.size())
- return false;
- for (size_t i = 0; i < lhs.m_buffer.size(); i++)
- {
- if (lhs.m_buffer[i] != rhs.m_buffer[i])
- return false;
- }
- return true;
- }
- bool operator!=(const BigNum& lhs, const BigNum& rhs)
- {
- return !(lhs == rhs);
- }
- bool operator<(const BigNum& lhs, const BigNum& rhs)
- {
- if (lhs.m_isNegative != rhs.m_isNegative)
- return lhs.m_isNegative == true;
- if (lhs.m_buffer.size() != rhs.m_buffer.size())
- return lhs.m_buffer.size() < rhs.m_buffer.size();
- std::string left(lhs.m_buffer.rbegin(), lhs.m_buffer.rend());
- std::string right(rhs.m_buffer.rbegin(), rhs.m_buffer.rend());
- for (size_t i = 0; i < left.size(); i++)
- {
- if (left[i] != right[i])
- {
- if (left[i] < right[i])
- return true;
- else
- return false;
- }
- }
- return false;
- }
- bool operator>(const BigNum& lhs, const BigNum& rhs)
- {
- return !(lhs < rhs) && lhs != rhs;
- }
- bool operator<=(const BigNum& lhs, const BigNum& rhs)
- {
- return lhs < rhs || lhs == rhs;
- }
- bool operator>=(const BigNum& lhs, const BigNum& rhs)
- {
- return lhs > rhs || lhs == rhs;
- }
- std::ostream& operator<<(std::ostream& lhs, const BigNum& rhs)
- {
- if (rhs.m_isNegative)
- {
- lhs << "-";
- }
- lhs << std::string(rhs.m_buffer.rbegin(), rhs.m_buffer.rend());
- return lhs;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement