F. Дроби v0.3

Продолжим разработку класса Fraction, который реализует предлагаемые дроби.

Реализуйте бинарные операторы:

  • + — сложение дробей, создаёт новую дробь;
  • - — вычитание дробей, создаёт новую дробь;
  • += — сложение дробей, изменяет дробь, переданную слева;
  • -= — вычитание дробей, изменяет дробь, переданную слева.

Примечание

Будем считать, что пользователь знает о запрете деления на ноль.
Все числа в данной задаче будут положительными.
Все поля и методы, не требуемые в задаче, следует инкапсулировать (называть с использованием ведущих символов нижнего подчёркивания).

Ваше решение должно содержать только классы и функции.
В решении не должно быть вызовов инициализации требуемых классов.

Пример

Ввод

a = Fraction(1, 3)
b = Fraction(1, 2)
c = a + b
print(a, b, c, a is c, b is c)

Вывод

1/3 1/2 5/6 False False

Ввод

a = Fraction(1, 8)
c = b = Fraction(3, 8)
b -= a
print(a, b, c, b is c)

Вывод

1/8 1/4 1/4 True

Решение

Добавляем немного математических операций в наш класс. По сути, все самое сложное мы сделали в первых двух задачах и теперь решение задач носит экстенсивный характер. Самая большая трудность, кторую мы можем встетить по пути – подзабытая математика.

Посмотреть код

Решение

Python
class Fraction():
    def __init__(self, *args) -> None:
        if isinstance(args[0], str):
            self.__num, self.__den = [int(c) for c in args[0].split('/')]
        else:
            self.__num = args[0]
            self.__den = args[1]
        self.__reduction()

    def __sign(self):
        return -1 if self.__num < 0 else 1

    def __neg__(self) -> 'Fraction':
        return Fraction(-self.__num, self.__den)

    def __add__(self, other) -> 'Fraction':
        denominator = self.denominator() * other.denominator()
        numerator = self.__num * other.__den + other.__num * self.__den
        return Fraction(numerator, denominator)

    def __sub__(self, other) -> 'Fraction':
        denominator = self.denominator() * other.denominator()
        numerator = self.__num * other.__den - other.__num * self.__den
        return Fraction(numerator, denominator)

    def __iadd__(self, other) -> 'Fraction':
        common_denominator = self.denominator() * other.denominator()
        self.__num = self.__num * other.__den + other.__num * self.__den
        self.__den = common_denominator
        self.__reduction()
        return self

    def __isub__(self, other) -> 'Fraction':
        common_denominator = self.denominator() * other.denominator()
        self.__num = self.__num * other.__den - other.__num * self.__den
        self.__den = common_denominator
        self.__reduction()
        return self

    def __gcd(self, a, b) -> int:
        while b:
            a, b = b, a % b
        return abs(a)

    def __reduction(self) -> tuple:
        __gcd = self.__gcd(self.__num, self.__den)
        self.__num //= __gcd
        self.__den //= __gcd

        if self.__den < 0:
            self.__num = -self.__num
            self.__den = abs(self.__den)
        return self.__num, self.__den

    def __str__(self) -> str:
        return f'{self.__num}/{self.__den}'

    def __repr__(self) -> str:
        return f"Fraction('{self.__num}/{self.__den}')"

    def numerator(self, *args) -> int:
        if len(args):
            self.__num = args[0] * self.__sign()
            self.__reduction()
        return abs(self.__num)

    def denominator(self, *args) -> int:
        if len(args):
            self.__den = args[0]
        self.__reduction()
        return abs(self.__den)
Подписаться
Уведомить о
guest
3 комментариев
Старые
Новые Популярные
Межтекстовые Отзывы
Посмотреть все комментарии
Степан
18.08.2024 17:03

Совсем забыл, что можно просто перемножить знаменатели – поэтому вспомнил про нахождение НОК через НОД. Ну, вдруг кому пригодится проверить себя
def __add__(self, other):
lcm = self._denominator * other._denominator // Fraction.__gcd(self._denominator, other._denominator)
multiplier_1, multiplier_2 = lcm // self._denominator, lcm // other._denominator
self_numerator = multiplier_1 * self._numerator
self_denominator = multiplier_1 * self._denominator
other_numerator = multiplier_2 * other._numerator
new_numerator, new_denominator = self_numerator + other_numerator, self_denominator
return Fraction(new_numerator, new_denominator)

Алексей
Алексей
11.09.2024 17:02

Сергей, здравствуйте,

Подскажите, в использовании common_denominator = self.denominator() * other.denominator() есть какой-то дополнительный смысл?
У меня Яндекс принял такой вариант:
def __isub__(self, other):
        self.__num = self.__num * other.__den – other.__num * self.__den
        self.__den = self.__den * other.__den
        self.__reduction()
        return self
Спасибо.