Files
Dmitry Rudakov 7504a12f6a Upload to git
2026-06-05 20:25:41 +05:00

195 lines
5.1 KiB
C++

#pragma once
#include <cstdint>
#include <iostream>
#include <numeric>
#include <ostream>
class Rational
{
public:
// Конструктор по умолчанию: 0/1
Rational() = default;
// Конструктор числителя
Rational(int numerator)
: numerator_{ numerator },
denominator_{ 1 } {
Reduction();
}
// Конструктор из числителя и знаменателя
Rational(int numerator, int denominator)
: numerator_{ numerator },
denominator_{ denominator } {
Reduction();
}
// Копирующий конструктор
Rational(const Rational& other)
: numerator_{other.numerator_},
denominator_(other.denominator_) {
}
// Возвращает обратную дробь
Rational Inv() const {
return Rational(denominator_, numerator_);
}
// Получить числитель
int GetNumerator() const {
return numerator_;
}
// Получить знаменатель
int GetDenominator() const {
return denominator_;
}
// Перегрузка оператора присваивания
Rational& operator=(const Rational&) = default;
// Унарный плюс
Rational operator+() const {
return *this;
return {numerator_, denominator_};
}
// Унарный минус
Rational operator-() const {
return Rational(-numerator_, denominator_);
}
// Сложение с присваиванием
Rational& operator+=(const Rational& other) {
numerator_ = numerator_ * other.denominator_ +
other.numerator_ * denominator_;
denominator_ = denominator_ * other.denominator_;
Reduction();
return *this;
}
// Вычитание с присваиванием
Rational& operator-=(const Rational& other) {
numerator_ = numerator_ * other.denominator_ -
other.numerator_ * denominator_;
denominator_ = denominator_ * other.denominator_;
Reduction();
return *this;
}
// Умножение с присваиванием
Rational& operator*=(const Rational& other) {
numerator_ = numerator_ * other.numerator_;
denominator_ = denominator_ * other.denominator_;
Reduction();
return *this;
}
// Деление с присваиванием
Rational& operator/=(const Rational& other) {
numerator_ *= other.denominator_;
denominator_ *= other.numerator_;
Reduction();
return *this;
}
// Сложение
Rational operator+(const Rational& other) const {
Rational result(*this);
result += other;
return result;
}
// Вычитание
Rational operator-(const Rational& other) const {
Rational result(*this);
result -= other;
return result;
}
// Умножение
Rational operator*(const Rational& other) const {
Rational result(*this);
result *= other;
return result;
}
// Деление
Rational operator/(const Rational& other) const {
Rational result(*this);
result /= other;
return result;
}
// Проверка равенства дробей
bool operator==(const Rational& other) const {
return static_cast<std::int64_t>(numerator_) * other.denominator_ ==
static_cast<std::int64_t>(other.numerator_) * denominator_;
}
// Трехстороннее сравнение
auto operator<=>(const Rational& other) const {
return static_cast<std::int64_t>(numerator_) * other.denominator_ <=>
static_cast<std::int64_t>(other.numerator_) * denominator_;
}
// Вывод дроби в поток
friend std::ostream& operator<<(std::ostream& os, const Rational& r) {
if (r.denominator_ == 1) {
os << r.numerator_;
} else {
os << r.numerator_ << " / " << r.denominator_;
}
return os;
}
// Чтение дроби из потока
friend std::istream& operator>>(std::istream& is, Rational& r) {
int n;
int d;
char div;
is >> n;
if (!(is >> std::ws >> div)) {
r = Rational(n, 1);
return is;
}
if (div != '/') {
is.unget();
r = Rational(n, 1);
return is;
}
is >> d;
if (!is || d == 0) {
is.setstate(std::ios::failbit);
r = Rational(n, 1);
} else {
r = Rational(n, d);
}
return is;
}
private:
int numerator_ = 0;
int denominator_ = 1;
// Нормализация дроби
void Reduction() {
if (numerator_ == 0) {
denominator_ = 1;
return;
}
if (denominator_ < 0) {
numerator_ = -numerator_;
denominator_ = -denominator_;
}
const int divisor = std::gcd(numerator_, denominator_);
numerator_ /= divisor;
denominator_ /= divisor;
}
};