Как реализовать класс Decimal для работы с десятичными целыми числами со знаком произвольной длины?

Задание такое: «Создать класс Decimal для работы с десятичными целыми числами со знаком произвольной длины. Число должно быть представлено строкой типа string, каждый символ которой — десятичная цифра, знак стоит слева первым и представлен символами '+' (может отсутствовать) или '-'. Реализовать арифметические операции сложения и вычитания, а также сравнения на равенство и на больше.»


Ответы (1 шт):

Автор решения: Damir Hakimof

ДЗ нужно выполнять самому. Я лишь могу представить код, написанный шальной рукой на мутную голову - никаких комментариев нет и гарантий безопасности тоже:

#include <string>
#include <algorithm>
#include <stdexcept>

class Decimal {
private:
  std::string value;
  bool is_negative = false;

  static std::string add_absolute(const std::string& a, const std::string& b) {
    std::string result;
    int i = a.length() - 1;
    int j = b.length() - 1;
    int carry = 0;

    while (i >= 0 || j >= 0 || carry > 0) {
      int digit_a = (i >= 0) ? (a[i--] - '0') : 0;
      int digit_b = (j >= 0) ? (b[j--] - '0') : 0;
      int sum = digit_a + digit_b + carry;
      carry = sum / 10;
      result.push_back((sum % 10) + '0');
    }

    std::reverse(result.begin(), result.end());
    return result;
  }

  static std::string subtract_absolute(const std::string& a, const std::string& b) {
    std::string result;
    int i = a.length() - 1;
    int j = b.length() - 1;
    int borrow = 0;

    while (i >= 0) {
      int digit_a = (a[i] - '0') - borrow;
      int digit_b = (j >= 0) ? (b[j] - '0') : 0;

      if (digit_a < digit_b) {
        digit_a += 10;
        borrow = 1;
      } else {
        borrow = 0;
      }

      result.push_back((digit_a - digit_b) + '0');
      --i;
      --j;
    }

    while (result.size() > 1 && result.back() == '0') {
      result.pop_back();
    }

    std::reverse(result.begin(), result.end());
    return result;
  }

  static bool less_absolute(const std::string& a, const std::string& b) {
    if (a.length() != b.length()) {
      return a.length() < b.length();
    }
    return a < b;
  }

  void normalize() {
    size_t non_zero = value.find_first_not_of('0');
    if (non_zero == std::string::npos) {
      value = "0";
      is_negative = false;
      return;
    }
    value = value.substr(non_zero);

    if (value == "0") {
      is_negative = false;
    }
  }

public:
  Decimal(const std::string& num) {
    if (num.empty()) {
      throw std::invalid_argument("Empty string");
    }

    size_t start = 0;
    if (num[0] == '+' || num[0] == '-') {
      is_negative = (num[0] == '-');
      start = 1;
    } else {
      is_negative = false;
    }

    if (num.substr(start).empty()) {
      throw std::invalid_argument("Invalid number format");
    }

    for (size_t i = start; i < num.size(); ++i) {
      if (!isdigit(num[i])) {
        throw std::invalid_argument("Invalid digit in number");
      }
    }

    value = num.substr(start);
    normalize();
  }

  Decimal operator+(const Decimal& other) const {
    Decimal result("0");
    
    if (is_negative == other.is_negative) {
      result.value = add_absolute(value, other.value);
      result.is_negative = is_negative;
    } else {
      if (less_absolute(value, other.value)) {
        result.value = subtract_absolute(other.value, value);
        result.is_negative = other.is_negative;
      } else {
        result.value = subtract_absolute(value, other.value);
        result.is_negative = is_negative;
      }
    }
    
    result.normalize();
    return result;
  }

  Decimal operator-(const Decimal& other) const {
    Decimal result("0");
    
    if (is_negative != other.is_negative) {
      result.value = add_absolute(value, other.value);
      result.is_negative = is_negative;
    } else {
      if (less_absolute(value, other.value)) {
        result.value = subtract_absolute(other.value, value);
        result.is_negative = !is_negative;
      } else {
        result.value = subtract_absolute(value, other.value);
        result.is_negative = is_negative;
      }
    }
    
    result.normalize();
    return result;
  }

  bool operator==(const Decimal& other) const {
    return is_negative == other.is_negative && value == other.value;
  }

  bool operator!=(const Decimal& other) const {
    return !(*this == other);
  }

  bool operator<(const Decimal& other) const {
    if (is_negative != other.is_negative) {
      return is_negative;
    }
    
    if (is_negative) {
      return less_absolute(other.value, value);
    } else {
      return less_absolute(value, other.value);
    }
  }

  bool operator>(const Decimal& other) const {
    return other < *this;
  }

  bool operator<=(const Decimal& other) const {
    return !(*this > other);
  }

  bool operator>=(const Decimal& other) const {
    return !(*this < other);
  }

  std::string toString() const {
    return (is_negative ? "-" : "") + value;
  }
};
→ Ссылка