F. Корень зла 2

В одной из первых лекций вы уже решали задачу о поиске корней уравнения. Давайте модернизируем её.

Напишите функцию find_roots, принимающую три параметра: коэффициенты уравнения и возвращающую его корни в виде кортежа из двух значений.

Так же создайте два собственных исключения NoSolutionsError и InfiniteSolutionsError, которые будут вызваны в случае отсутствия и бесконечного количества решений уравнения соответственно.

Если переданные коэффициенты не являются рациональными числами, вызовите исключение TypeError.

Примечание

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

Пример

Ввод

print(find_roots(0, 0, 1))

Вывод

Вызвано исключение NoSolutionsError

Ввод

print(find_roots(1, 2, 1))

Вывод

(-1.0, -1.0)

Решение

Чуть модифицированная версия задачи Q. Корень зла.

Нужно добавить вызов исключений, вместо вывода соответствующих сообщений и удваивать корень, если он оказался один.

Не забываем объявить класс исключений. Их можно сделать пустыми (pass).

Организовать проверку можно несколькими способами – в решении для этого используется функция type(). Можно воспользоваться isinstance(), но так будет чуть более громоздко.

В остальном это практически точная копия решения первой задачи.

Несмотря на то, что его можно слегка оптимизировать и “слить” условия, приводящие к одинаковому результату в одно, что сделает код короче, я, в угоду читабельности, и сохранения академичности решения оставляю его ровно в том же шаблоне, что был выбран для первого решения.

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

Решение

Python
class InfiniteSolutionsError(Exception):
    pass


class NoSolutionsError(Exception):
    pass


def find_roots(a, b, c):

    roots = ()

    if not all(type(num) in (int, float) for num in (a, b, c)):
        raise TypeError

    if a == b == c == 0:
        raise InfiniteSolutionsError('Infinite solutions')
    elif a == 0 and b != 0 and c != 0:
        roots = (-(c / b), -(c / b))
    elif a == b == 0:
        raise NoSolutionsError('No solution')
    elif a == c == 0:
        roots = (0, 0)
    else:
        disc = (b ** 2) - (4 * a * c)
        if disc == 0:
            roots = ((-b) / (2 * a), (-b) / (2 * a))
        elif disc > 0:
            x1 = (-b - (disc ** 0.5)) / (2 * a)
            x2 = (-b + (disc ** 0.5)) / (2 * a)
            roots = tuple(sorted([x1, x2]))
        else:
            raise NoSolutionsError('No solution')
    return roots