D. Дроби v0.1

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

Начнём разработку класса Fraction, который реализует предлагаемые дроби.

Предусмотрите возможность инициализации дроби с помощью двух целых чисел или строки в формате <числитель>/<знаменатель>.
В случаях наличия общего делителя у числителя и знаменателя, дробь следует сократить.

А также реализуйте методы:

  • numerator() — возвращает значение числителя;
  • numerator(number) — изменяет значение числителя и производит сокращение дроби, если это необходимо;
  • denominator() – возвращает значение знаменателя;
  • denominator(number) — изменяет значение знаменателя и производит сокращение дроби, если необходимо;
  • __str__ — возвращает строковое представление дроби в формате <числитель>/<знаменатель>;
  • __repr__ — возвращает описание объекта в формате Fraction(<числитель>, <знаменатель>).

Примечание

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

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

Пример

Ввод

fraction = Fraction(3, 9)
print(fraction, repr(fraction))
fraction = Fraction('7/14')
print(fraction, repr(fraction))

Вывод

1/3 Fraction(1, 3)
1/2 Fraction(1, 2)

Ввод

fraction = Fraction(3, 210)
print(fraction, repr(fraction))
fraction.numerator(10)
print(fraction.numerator(), fraction.denominator())
fraction.denominator(2)
print(fraction.numerator(), fraction.denominator())

Вывод

1/70 Fraction(1, 70)
1 7
1 2

Решение

Нам предлагают создать класс Fraction, аналогичный существующему в python.

В первом задании все достаточно прозаично – от нас требуют написать представление нашей дробы (__str__ и __repr__)б что мы уже умеем делать после выполнения серии задач про классную точку. Помимо представления класса нам потребуется написать методы, позволяющие задать или получить значения числителя и знаменателя. Кроме того, нужно не забывать, что 2/4 это 1/2, и значит, нам надо уметь сокращать дроби. Для этого нам потребуется вспомнить как искать наибольший общий делитель, чтобы правильно сократить дробь.

И пусть вас не смущает то, что наш класс будет называться аналогично существующему в python. При том, что они довольно похожи, у наших классов будут и различия. В этой адаче, например наши методы должны уметь менять числитель и знаменатель, в то время как в стандартной реализации одноименные методы только возвращают соотвествуюшие значения. Задание новых возможно только путем создания новых объектов.

Итак, помимо методов, которые мы должны описать, мы создаем метод __gcd для поиска НОД и метод __reduction() для сокращения дроби.

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

Решение

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 __gcd(self, a, b):
        while b != 0:
            a, b = b, a % b
        return abs(a)

    def __reduction(self):
        gcd = self.__gcd(self.__num, self.__den)
        self.__num = self.__num // gcd
        self.__den = self.__den // gcd
        return self

    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):
        if len(args):
            self.__num = args[0]
            self.__reduction()
        return self.__num

    def denominator(self, *args):
        if len(args):
            self.__den = args[0]
            self.__reduction()
        return self.__den
Подписаться
Уведомить о
guest
2 комментариев
Старые
Новые Популярные
Межтекстовые Отзывы
Посмотреть все комментарии
Артём
Артём
18.03.2024 20:09

Не пойму в чём разница?

Вот так Яндекс не принимает:

class Fraction:
    def __init__(self, *args):
        if isinstance(args[0], str):
            self.a, self.b = [int(x) for x in args[0].split(‘/’)]
        else:
            self.a, self.b = [x for x in args]
        self.nod()

    def nod(self):
        x = self.a
        y = self.b
        while y != 0:
            x, y = y, x % y
        self.a = self.a // x
        self.b = self.b // x

    def __str__(self) -> str:
        return f'{self.a}/{self.b}’

    def __repr__(self) -> str:
        return f’Fraction({self.a}, {self.b})’

Так всё устраивает:
class Fraction:
def __init__(self, *args):
if isinstance(args[0], str):
self.a, self.b = [int(x) for x in args[0].split(‘/’)]
else:
self.a, self.b = [x for x in args]
self.__nod()

def __nod(self):
x = self.a
y = self.b
while y != 0:
x, y = y, x % y
self.a = self.a // x
self.b = self.b // x

def __str__(self) -> str:
return f'{self.a}/{self.b}’

def __repr__(self) -> str:
return f’Fraction({self.a}, {self.b})’

def numerator(self, *args):
if args:
self.a = args[0]
self.__nod()
return self.a

def denominator(self, *args):
if args:
self.b = args[0]
self.__nod()
return self.b

Не нашёл объяснения. В чём разница в объявлении приватного метода, кроме того, что мы не можем его вне класса вызвать? Локально работает и так и так, но Яндекс ругается на:
Completion status: ABNORMAL_EXIT
Term sig: null
Error code: 2

Не понимаю логику…

Последний раз редактировалось 9 месяцев назад Артём ем