fixes
This commit is contained in:
+129
@@ -0,0 +1,129 @@
|
||||
from decimal import Decimal, getcontext
|
||||
|
||||
# увеличиваем точность для больших чисел
|
||||
getcontext().prec = 50
|
||||
|
||||
|
||||
class Fraction:
|
||||
def __init__(self, numerator, denominator):
|
||||
self._numerator = None
|
||||
self._denominator = None
|
||||
|
||||
self.set_numerator(numerator)
|
||||
self.set_denominator(denominator)
|
||||
|
||||
self.validate_proper_fraction()
|
||||
|
||||
# ------------------------
|
||||
# УСТАНОВКА ЧИСЛИТЕЛЯ
|
||||
def set_numerator(self, numerator):
|
||||
self._numerator = self.validate_numerator(numerator)
|
||||
|
||||
# ------------------------
|
||||
# УСТАНОВКА ЗНАМЕНАТЕЛЯ
|
||||
def set_denominator(self, denominator):
|
||||
self._denominator = self.validate_denominator(denominator)
|
||||
|
||||
@staticmethod
|
||||
def validate_numerator(numerator) -> int:
|
||||
try:
|
||||
num = Decimal(numerator)
|
||||
except:
|
||||
raise ValueError("Числитель должен быть числом")
|
||||
|
||||
if num != num.to_integral_value():
|
||||
raise ValueError("Числитель должен быть целым числом")
|
||||
|
||||
num = int(num)
|
||||
|
||||
if num <= 0:
|
||||
raise ValueError("Числитель должен быть положительным")
|
||||
|
||||
return num
|
||||
|
||||
@staticmethod
|
||||
def validate_denominator(denominator) -> int:
|
||||
try:
|
||||
den = Decimal(denominator)
|
||||
except:
|
||||
raise ValueError("Знаменатель должен быть числом")
|
||||
|
||||
if den != den.to_integral_value():
|
||||
raise ValueError("Знаменатель должен быть целым числом")
|
||||
|
||||
den = int(den)
|
||||
|
||||
if den <= 0:
|
||||
raise ValueError("Знаменатель должен быть положительным")
|
||||
|
||||
return den
|
||||
|
||||
# ------------------------
|
||||
# ПРОВЕРКА ПРАВИЛЬНОЙ ДРОБИ
|
||||
def validate_proper_fraction(self):
|
||||
if self._numerator >= self._denominator:
|
||||
raise ValueError(
|
||||
"Это не правильная дробь (числитель должен быть меньше знаменателя)"
|
||||
)
|
||||
|
||||
# ------------------------
|
||||
# МЕТОД №1: В ПРОЦЕНТЫ (всегда 2 знака)
|
||||
def to_percent(self) -> str:
|
||||
value = (Decimal(self._numerator) / Decimal(self._denominator)) * Decimal(100)
|
||||
return f"{value:.2f}"
|
||||
|
||||
# ------------------------
|
||||
# МЕТОД №2: СУММА ЦИФР ЗНАМЕНАТЕЛЯ
|
||||
def sum_digits_denominator(self) -> int:
|
||||
return sum(int(d) for d in str(self._denominator))
|
||||
|
||||
# ------------------------
|
||||
# СТРОКА ИНФОРМАЦИИ
|
||||
def info(self) -> str:
|
||||
return (
|
||||
f"Дробь: {self._numerator}/{self._denominator} | "
|
||||
f"Проценты: {self.to_percent()}% | "
|
||||
f"Сумма цифр знаменателя: {self.sum_digits_denominator()}"
|
||||
)
|
||||
|
||||
|
||||
# ------------------------
|
||||
# ВВОД С ПОДДЕРЖКОЙ 1e32
|
||||
def input_number(prompt: str):
|
||||
while True:
|
||||
value = input(prompt).strip()
|
||||
try:
|
||||
Decimal(value) # проверка валидности
|
||||
return value
|
||||
except:
|
||||
print("Ошибка: введите число (поддерживается формат 1e32)")
|
||||
|
||||
|
||||
def input_fraction() -> Fraction:
|
||||
while True:
|
||||
try:
|
||||
num = input_number("Введите числитель: ")
|
||||
den = input_number("Введите знаменатель: ")
|
||||
return Fraction(num, den)
|
||||
except ValueError as e:
|
||||
print("Ошибка:", e)
|
||||
|
||||
|
||||
# ------------------------
|
||||
def main():
|
||||
print("Ввод дроби с клавиатуры:")
|
||||
frac_input = input_fraction()
|
||||
|
||||
# Константы
|
||||
frac1 = Fraction(1, 2)
|
||||
frac2 = Fraction("32", "540")
|
||||
|
||||
fractions = [frac_input, frac1, frac2]
|
||||
|
||||
print("\nРезультаты:")
|
||||
for f in fractions:
|
||||
print(f.info())
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user