Как надёжно исследовать квадратное уравнение в программе?
Задача о квадратном уравнении проверяет не формулу корней, а полноту классификации входа. Коэффициент при квадрате может оказаться нулём, дискриминант — положительным, нулевым…
Задача о квадратном уравнении проверяет не формулу корней, а полноту классификации входа. Коэффициент при квадрате может оказаться нулём, дискриминант — положительным, нулевым или отрицательным, а вещественная арифметика — дать значение рядом с нулём из-за округления.
Вырожденный коэффициент
Сначала проверяют a. Если a = 0, уравнение становится линейным bx + c = 0. При b = 0 остаются два случая: c = 0 даёт бесконечно много решений, ненулевое c — ни одного. Только после этой ветки безопасно делить на 2a.
Целые коэффициенты
Для целочисленного входа дискриминант D = b² − 4ac вычисляется точно, если тип не переполняется. Знак D определяет число вещественных корней. Перед умножением больших коэффициентов нужно оценить диапазон и при необходимости использовать более широкий целый тип.
Вещественный вход
Сравнение с точным нулём ненадёжно, если коэффициенты получены измерением или предыдущими вычислениями. Вводят допуск eps и рассматривают |D| ≤ eps как близость к нулю. Сам eps выбирают с учётом масштаба данных, иначе абсолютный порог окажется слишком грубым или слишком строгим.
Численная устойчивость
Формула −b ± √D может терять значащие цифры при вычитании близких величин. Один корень устойчивее вычислять через выражение с большим по модулю числителем, а второй получать из произведения корней c/a. Этот приём важен в вычислительной задаче, хотя символические ответы эквивалентны.
Набор тестов
Проверьте обычные два корня, двойной корень, отсутствие вещественных корней, линейное уравнение, тождество и противоречие. Добавьте большие коэффициенты и D около нуля. Полный набор демонстрирует, что алгоритм исследует уравнение, а не работает только на школьном «идеальном» случае.
Ветвление должно покрывать всю классификацию
Сначала проверяется линейный случай a = 0, потому что деление на 2a там недопустимо. Для вещественных коэффициентов сравнение с нулём выполняют с допуском, согласованным с масштабом входа. При положительном дискриминанте более устойчивый вариант избегает вычитания близких чисел, вычисляя один корень через q, а второй через произведение корней.
from math import copysign, sqrt
def quadratic_roots(a: float, b: float, c: float) -> tuple[str, list[float]]:
if a == 0:
if b == 0:
return ("all", []) if c == 0 else ("none", [])
return "one", [-c / b]
d = b * b - 4 * a * c
if d < 0:
return "none", []
if d == 0:
return "one", [-b / (2 * a)]
q = -0.5 * (b + copysign(sqrt(d), b))
return "two", [q / a, c / q]Код рассматривает действительные корни; комплексные требуют другого контракта. Точное сравнение d с нулём здесь подходит для демонстрации, а для измеренных входов следует определить масштабный допуск.
Практика: проверка по Виету
Составьте тесты для линейного уравнения, отсутствия решений, двойного корня, двух корней и коэффициентов разного масштаба. Для пары корней проверьте сумму −b/a и произведение c/a с допуском. Затем сравните обычную школьную формулу и устойчивый вариант на b большого модуля при маленьком c. Объясните, где теряются значащие разряды и почему перестановка алгебраически равных действий меняет машинный результат.
Источники
- МФТИ: Программа вступительного испытания по информатике и информационно-коммуникационным технологиям.
- МФТИ: Пример вступительного испытания по информатике.
- МФТИ: Вступительные испытания в 2026 году.
- Семакин И.Г., Хеннер Е.К., Шеина Т.Ю. Информатика. 11 класс. Базовый уровень.