Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #ifndef FIVT_4_BIGINTEGER_H
- #define FIVT_4_BIGINTEGER_H
- #include <iostream>
- #include <vector>
- #include <string>
- typedef int data;
- const data BASE = 10;
- class BigInteger {
- public:
- BigInteger(int integer_value);
- BigInteger();
- BigInteger(const BigInteger& other); // copy-constructor
- BigInteger(BigInteger&& other) noexcept; // move-constructor
- BigInteger(const std::vector<data>& _numbers, bool _is_positive);
- BigInteger& operator = (const BigInteger& other);
- BigInteger& operator = (BigInteger&& other) noexcept;
- friend BigInteger operator + (const BigInteger& that, const BigInteger& other);
- friend BigInteger operator - (const BigInteger& that, const BigInteger& other);
- friend BigInteger operator * (const BigInteger& that, const BigInteger& other);
- friend BigInteger operator / (const BigInteger& that, const BigInteger& other);
- friend BigInteger operator % (const BigInteger& that, const BigInteger& other);
- friend BigInteger& operator += (BigInteger& that, const BigInteger& other);
- friend int& operator += (int& that, const BigInteger& other);
- friend BigInteger& operator -= (BigInteger& that, const BigInteger& other);
- friend int& operator -= (int& that, const BigInteger& other);
- friend BigInteger& operator *= (BigInteger& that, const BigInteger& other);
- friend int& operator *= (int& that, const BigInteger& other);
- friend BigInteger& operator /= (BigInteger& that, const BigInteger& other);
- friend int& operator /= (int& that, const BigInteger& other);
- friend BigInteger& operator %= (BigInteger& that, const BigInteger& other);
- friend int& operator %= (int& that, const BigInteger& other);
- BigInteger operator-() const;
- BigInteger& operator++(); // prefix-form
- BigInteger operator++(int); // postfix-form
- BigInteger& operator--(); // prefix-form
- BigInteger operator--(int); // postfix-form
- bool operator==(const BigInteger& other) const;
- bool operator!=(const BigInteger& other) const;
- bool operator<=(const BigInteger& other) const;
- bool operator>=(const BigInteger& other) const;
- bool operator<(const BigInteger& other) const;
- bool operator>(const BigInteger& other) const;
- // input - output
- friend std::ostream &operator<<(std::ostream& stream, const BigInteger& big_integer);
- friend std::istream &operator>>(std::istream& stream, BigInteger& big_integer);
- // type conversion
- explicit operator int();
- explicit operator bool();
- // other methods
- std::string toString() const;
- bool GetIsPositive() const;
- size_t GetNumberOfDigits() const;
- std::vector<data> GetVectorOfDigits() const;
- void SetIsPositive(bool sign);
- void MultiplyOnBase();
- void DeleteLeadZeros();
- private:
- std::vector<data> vector_of_digits;
- bool is_positive;
- bool CompareByAbs(const BigInteger& other) const;
- };
- BigInteger::BigInteger(const std::vector<data>& _numbers, bool _is_positive) {
- vector_of_digits = _numbers;
- is_positive = _is_positive;
- }
- BigInteger::BigInteger(int integer_value) {
- std::vector<data> digits;
- is_positive = (integer_value >= 0);
- integer_value = ( integer_value < 0 )? -integer_value : integer_value;
- if ( integer_value == 0 ) {
- digits.push_back(0);
- } else {
- unsigned long long current_rest = 0;
- unsigned long long prev_rest = 0;
- unsigned long long charge = BASE;
- size_t iter = 0;
- while (true) {
- prev_rest = current_rest;
- current_rest = integer_value % charge;
- try {
- digits.push_back(static_cast<data>((current_rest - prev_rest) / (charge / BASE)));
- if (current_rest == static_cast<unsigned int>(integer_value)) {
- break;
- }
- } catch (...) {
- std::cerr<<"bad_cast in: BigInteger(int integer_value) ";
- exit(2);
- }
- charge *= BASE;
- iter++;
- if (iter > 20) {
- std::cerr<<"loop in: BigInteger(int integer_value) ";
- exit(2);
- }
- }
- }
- vector_of_digits = digits;
- }
- BigInteger::BigInteger() {
- std::vector<data> digits;
- vector_of_digits = digits;
- is_positive = true;
- }
- BigInteger::BigInteger(const BigInteger &other) {
- vector_of_digits = other.GetVectorOfDigits();
- is_positive = other.GetIsPositive();
- }
- BigInteger::BigInteger(BigInteger &&other) noexcept {
- vector_of_digits = other.vector_of_digits;
- is_positive = other.is_positive;
- other.vector_of_digits.clear();
- other.is_positive = true;
- }
- std::vector<data> BigInteger::GetVectorOfDigits() const {
- return vector_of_digits;
- }
- bool BigInteger::GetIsPositive() const {
- return is_positive;
- }
- BigInteger& BigInteger::operator=(const BigInteger &other) {
- this->vector_of_digits = other.GetVectorOfDigits();
- this->is_positive = other.GetIsPositive();
- return *this;
- }
- BigInteger& BigInteger::operator=(BigInteger &&other) noexcept {
- this->vector_of_digits = other.vector_of_digits;
- this->is_positive = other.is_positive;
- other.vector_of_digits.clear();
- other.is_positive = true;
- return *this;
- }
- BigInteger operator + (const BigInteger& that, const BigInteger& other) {
- // this is positive, other is negative
- if (that.GetIsPositive() && !other.GetIsPositive()) { // (+a) + (-b)
- BigInteger other_positive = other; // MEMORY!
- other_positive.SetIsPositive(true);
- return (that - other_positive);
- // this is negative, other is positive
- } else if (!that.GetIsPositive() && other.GetIsPositive()) { // (-a) + (+b)
- BigInteger this_positive = that; // MEMORY!
- this_positive.SetIsPositive(true);
- return (other - this_positive);
- // this & other are negative
- } else if (!that.GetIsPositive() && !other.GetIsPositive()) {
- BigInteger this_positive = that; // MEMORY!
- this_positive.SetIsPositive(true);
- BigInteger other_positive = other; // MEMORY!
- other_positive.SetIsPositive(true);
- return -(this_positive + other_positive);
- // both operands are positive
- } else {
- auto other_vector_of_numbers = other.GetVectorOfDigits();
- std::vector<data> result;
- size_t n = that.vector_of_digits.size();
- size_t m = other_vector_of_numbers.size();
- data to_next_charge = 0;
- for (size_t i = 0; i < n || i < m; ++i) {
- data rest = 0;
- data number = 0;
- try {
- number = static_cast<data>(((i < m) ? other_vector_of_numbers[i] : 0) +
- ((i < n) ? that.vector_of_digits[i] : 0) + to_next_charge);
- rest = static_cast<data>(number % BASE);
- } catch (...) {
- std::cerr<<"bad_cast in operator+";
- exit(3);
- }
- if ( number >= BASE) {
- to_next_charge = 1;
- number = rest;
- } else {
- to_next_charge = 0;
- }
- result.push_back(number);
- }
- if (to_next_charge != 0) {
- result.push_back(to_next_charge);
- }
- return {result, true};
- }
- }
- BigInteger operator-(const BigInteger& that, const BigInteger& other) {
- // this is positive, other is negative
- if (that.GetIsPositive() && !other.GetIsPositive()) {
- BigInteger other_positive = other; // (+a) - (-b)
- other_positive.SetIsPositive(true);
- return (that + other_positive);
- // this is negative, other is positive
- } else if (!that.GetIsPositive() && other.GetIsPositive()) { // (-a) - (+b)
- BigInteger this_positive = that;
- this_positive.SetIsPositive(true);
- BigInteger other_positive = other;
- other_positive.SetIsPositive(true);
- return -(this_positive + other_positive); // -((+a) + (+b))
- // this & other are negative
- } else if (!that.GetIsPositive() && !other.GetIsPositive()) { //(-a) - (-b)
- BigInteger this_positive = that;
- this_positive.SetIsPositive(true);
- BigInteger other_positive = other;
- other_positive.SetIsPositive(true);
- return (other_positive - this_positive);
- // both operands are positive
- } else { //(+a) - (+b)
- std::vector<data> result;
- // из большего - меньшее
- if ( that > other ) {
- auto other_vector_of_numbers = other.GetVectorOfDigits();
- size_t n = that.vector_of_digits.size();
- size_t m = other_vector_of_numbers.size();
- data to_next_charge = 0;
- int number = 0;
- if ( n < m ) {
- std::cerr<<" n < m in operator-";
- exit(1);
- }
- for (size_t i = 0; i < n || i < m; ++i) {
- number = (that.vector_of_digits[i] - ((i < m) ? other_vector_of_numbers[i] : 0) - to_next_charge);
- if (number < 0) {
- result.emplace_back(static_cast<data>(number + BASE));
- to_next_charge = 1;
- } else {
- result.push_back(static_cast<data>(number));
- to_next_charge = 0;
- }
- }
- // убираем нули в конце
- while (result.back() == 0 && result.size() > 1) {
- result.pop_back();
- }
- return {result, true};
- // сводим к вычитанию из большего меньшее
- } else if (that == other) {
- result.emplace_back(0);
- return {result, true};
- } else {
- return -(other - that);
- }
- }
- }
- BigInteger operator*(const BigInteger& that, const BigInteger& other) {
- size_t n = that.GetNumberOfDigits();
- size_t m = other.GetNumberOfDigits();
- // умножение длинного на короткое
- if ( n >= m ) {
- std::vector<data> this_vector = that.GetVectorOfDigits();
- std::vector<data> other_vector = other.GetVectorOfDigits();
- bool result_sign = that.GetIsPositive() & other.GetIsPositive();
- std::vector<BigInteger> parts;
- for (size_t j = 0; j < m; ++j) { // идем по короткому
- data to_next_charge = 0;
- std::vector<data> new_part(n + j);
- for (size_t i = 0; i < n; ++i) { // по длинному
- data value = (other_vector[j] * this_vector[i]) + to_next_charge;
- data rest = value % BASE;
- if ( rest < value ) { //число больше 10
- to_next_charge = (value - rest)/BASE;
- } else {
- to_next_charge = 0;
- }
- new_part[i + j] = rest;
- }
- if ( to_next_charge > 0 ) {
- new_part.push_back(to_next_charge);
- }
- parts.push_back({new_part,true});
- }
- BigInteger result = parts[0];
- for(size_t i = 1; i < parts.size(); ++i) {
- result += parts[i];
- }
- result.DeleteLeadZeros();
- result.SetIsPositive(result_sign);
- return result;
- } else {
- return (other * that);
- }
- }
- void BigInteger::MultiplyOnBase() {
- vector_of_digits.insert(vector_of_digits.begin(),0);
- }
- void BigInteger::DeleteLeadZeros() {
- while (vector_of_digits.back() == 0 && vector_of_digits.size() > 1) {
- vector_of_digits.pop_back();
- }
- }
- BigInteger operator / (const BigInteger& that, const BigInteger& other) {
- bool result_sign = that.GetIsPositive() && other.GetIsPositive();
- BigInteger other_positive = {other.GetVectorOfDigits(), true};
- BigInteger this_positive = {that.GetVectorOfDigits(), true};
- std::vector<data> result_vector;
- if (other_positive > this_positive) {
- result_vector.emplace_back(0);
- return {result_vector, true};
- } else if (other_positive == this_positive) {
- result_vector.emplace_back(1);
- return {result_vector, result_sign};
- } else { //this > other // what if this == {0}
- size_t n = that.GetNumberOfDigits();
- result_vector.resize(n); // число разрядов в частном не больше чем в делимом
- std::vector<data> this_vector = that.GetVectorOfDigits();
- BigInteger current_value;
- for (int i = n - 1; i >= 0; --i) {
- current_value.MultiplyOnBase();
- current_value.vector_of_digits[0] = this_vector[i]; //?? private
- // подбираем максимальное число x, такое что other * attempt <= curent_value
- for (data l = 0; l <= BASE; ++l) {
- BigInteger attempt({l}, true);
- BigInteger cur = other_positive * attempt;
- if (cur > current_value) {
- try {
- result_vector[i] = static_cast<data>(l - 1);
- current_value = current_value - other_positive * BigInteger({static_cast<data>(l - 1)}, true);
- } catch (...) {
- std::cerr<<"bad_cast in: operator/ ";
- exit(5);
- }
- current_value.DeleteLeadZeros();
- break;
- }
- }
- }
- BigInteger result {result_vector, result_sign};
- result.DeleteLeadZeros();
- return result;
- }
- }
- BigInteger operator % (const BigInteger& that, const BigInteger& other) {
- bool result_sign = that.GetIsPositive() & other.GetIsPositive();
- BigInteger other_positive = {other.GetVectorOfDigits(), true};
- BigInteger this_positive = {that.GetVectorOfDigits(), true};
- std::vector<data> result_vector;
- if (other_positive > this_positive) {
- return {that.GetVectorOfDigits(), result_sign};
- } else if (other_positive == this_positive) {
- result_vector.push_back(0);
- return {result_vector, result_sign};
- } else {
- size_t n = that.GetNumberOfDigits();
- std::vector<data> this_vector = that.GetVectorOfDigits();
- BigInteger current_value;
- for (int i = n - 1; i >= 0; --i) {
- current_value.MultiplyOnBase();
- current_value.vector_of_digits[0] = this_vector[i];
- // подбираем максимальное число x, такое что b * attempt <= curValue
- for (data l = 0; l <= BASE; ++l) {
- BigInteger cur = other_positive * l;
- if (cur > current_value) {
- current_value -= other_positive * (l-1);
- current_value.DeleteLeadZeros();
- break;
- }
- }
- }
- current_value.SetIsPositive( result_sign );
- return current_value;
- }
- }
- BigInteger& operator += (BigInteger& that, const BigInteger& other) {
- that = that + other;
- return (that);
- }
- int& operator+=(int& that, const BigInteger &other) {
- that = (int)(other + that);
- return that;
- }
- BigInteger& operator-=(BigInteger& that, const BigInteger& other) {
- that = (that - other);
- return (that);
- }
- int& operator-=(int& that, const BigInteger &other) {
- that = (int)(that - other);
- return (that);
- }
- BigInteger& operator*=(BigInteger& that, const BigInteger& other) {
- that = (that * other);
- return (that);
- }
- int& operator*=(int& that, const BigInteger& other) {
- that = (int)(that * other);
- return (that);
- }
- BigInteger& operator/=(BigInteger& that, const BigInteger& other) {
- that = (that / other);
- return (that);
- }
- int& operator/=(int& that, const BigInteger& other) {
- that = (int)(that / other);
- return (that);
- }
- BigInteger& operator%=(BigInteger& that, const BigInteger& other) {
- that = (that % other);
- return (that);
- }
- int& operator%=(int& that, const BigInteger& other) {
- that = (int)(that % other);
- return (that);
- }
- BigInteger BigInteger::operator-() const {
- try {
- BigInteger temp = {this->GetVectorOfDigits(), !this->GetIsPositive()};
- return temp;
- } catch (...) {
- std::cerr<<"operator-";
- exit(1);
- }
- }
- BigInteger& BigInteger::operator++() {
- (*this) = (*this) + BigInteger(1);
- return *this;
- }
- BigInteger BigInteger::operator++(int) {
- BigInteger temp = *this;
- (*this) = (*this) + BigInteger(1);
- return temp;
- }
- BigInteger& BigInteger::operator--() {
- (*this) = (*this) - BigInteger(1);
- return *this;
- }
- BigInteger BigInteger::operator--(int) {
- BigInteger temp = *this;
- (*this) = (*this) - BigInteger(1);
- return temp;
- }
- bool BigInteger::operator==(const BigInteger &other) const {
- size_t n = this->GetNumberOfDigits();
- if ( n != other.GetNumberOfDigits() ) {
- return false;
- } else {
- if ( this->GetIsPositive() != other.GetIsPositive() ) {
- return false;
- } else {
- auto this_vector = this->GetVectorOfDigits();
- auto other_vector = other.GetVectorOfDigits();
- for (size_t i = 0; i < n; ++i) {
- if (this_vector[i] != other_vector[i]) {
- return false;
- }
- }
- return true;
- }
- }
- }
- size_t BigInteger::GetNumberOfDigits() const {
- return vector_of_digits.size();
- }
- bool BigInteger::operator!=(const BigInteger &other) const {
- return !( *this == other );
- }
- bool BigInteger::operator<=(const BigInteger &other) const {
- bool is_equal = ( *this == other );
- bool is_less = (*this < other);
- return is_equal || is_less;
- }
- bool BigInteger::operator>=(const BigInteger &other) const {
- bool is_equal = ( *this == other );
- bool is_more = (*this > other);
- return is_equal || is_more;
- }
- bool BigInteger::CompareByAbs(const BigInteger &other) const { // is this < other by abs?
- size_t n = this->GetNumberOfDigits();
- size_t m = other.GetNumberOfDigits();
- if ( n < m ) {
- return true;
- } else if ( m == n ) {
- auto this_vector = this->GetVectorOfDigits();
- auto other_vector = other.GetVectorOfDigits();
- for (int i = n - 1; i >= 0; --i) { // start from the end
- if (this_vector[i] < other_vector[i]) {
- return true;
- } else if (this_vector[i] > other_vector[i]) {
- return false;
- }
- }
- return false;
- } else {
- return false;
- }
- }
- bool BigInteger::operator<(const BigInteger &other) const {
- bool is_less = false;
- // this - negative , other - positive
- if ( !this->GetIsPositive() && other.GetIsPositive() ) {
- is_less = true;
- // this - positive , other - negative
- } else if ( this->GetIsPositive() && !other.GetIsPositive() ) {
- is_less = false;
- // this & other have similar sign
- } else {
- // this & other negative
- if ( !this->GetIsPositive() && !other.GetIsPositive() ) {
- is_less = !(this->CompareByAbs(other));
- }
- // this & other positive
- if ( this->GetIsPositive() && other.GetIsPositive() ){
- is_less = this->CompareByAbs(other);
- }
- }
- return is_less && (*this != other);
- }
- bool BigInteger::operator>(const BigInteger &other) const {
- return (!(*this < other)) && (*this != other);
- }
- std::ostream& operator<<(std::ostream &stream, const BigInteger& big_integer) {
- std::vector<data> vector_of_digits = big_integer.GetVectorOfDigits();
- if ( !big_integer.is_positive ) {
- stream << '-';
- }
- for (int i = big_integer.GetNumberOfDigits() - 1; i >= 0; --i) {
- stream << vector_of_digits[i];
- }
- return stream;
- }
- std::istream& operator>>(std::istream &stream, BigInteger& big_integer) {
- std::string str;
- stream.setf(std::ios::skipws);
- stream >> str;
- int first_position_of_number = 0;
- if (str[0] == '-') {
- big_integer.is_positive = false;
- first_position_of_number = 1;
- if ( str.size() == 1 ) {
- std::string rest_of_str;
- stream >> rest_of_str;
- str.append(rest_of_str);
- }
- } else {
- big_integer.is_positive = true;
- }
- for (int i = str.size() - 1; i >= first_position_of_number; --i) {
- std::string digit = {str[i]};
- try {
- big_integer.vector_of_digits.emplace_back(static_cast<data&&>(std::stoi(digit, nullptr, BASE)));
- } catch (...){
- std::cerr<<"bad_cast in: operator>> ";
- exit(7);
- }
- }
- return stream;
- }
- BigInteger::operator int() {
- int int_value = 0;
- unsigned long long charge = 1;
- for (auto digit : this->GetVectorOfDigits()) {
- int_value += digit*charge;
- charge *= BASE;
- }
- return int_value;
- }
- BigInteger::operator bool() {
- for (auto digit : this->GetVectorOfDigits()) {
- if ( digit != 0 ) {
- return true;
- }
- }
- return false;
- }
- void BigInteger::SetIsPositive(bool sign) {
- this->is_positive = sign;
- }
- std::string BigInteger::toString() const {
- // std::string string_number = "";
- // if ( !this->GetIsPositive() ) {
- // string_number += "-";
- // }
- // for (size_t i = GetNumberOfDigits() - 1; i < GetNumberOfDigits(); --i) {
- //// try {
- //// std::string digit = std::to_string((vector_of_digits[i]));
- //// string_number.append(digit);
- //// } catch (...) {
- //// std::cout<<"toString exception";
- //// exit(1);
- //// }
- // string_number += '0' + vector_of_digits[i];
- // }
- return "1234";
- }
- #endif //FIVT_4_BIGINTEGER_H
Add Comment
Please, Sign In to add comment