Python для решения квадратных уравнений: эффективные алгоритмы
Решение квадратного уравнения в Python
Как найти корни квадратного уравнения с помощью дискриминанта?
Наиболее распространённый способ основан на вычислении дискриминанта. Для уравнения вида ax2 + bx + c = 0 дискриминант D = b2 - 4ac. При D > 0 два действительных корня, при D = 0 один корень, при D < 0 корни комплексные.
import math
def solve_quadratic(a, b, c):
if a == 0:
if b == 0:
return ('бесконечно много корней' if c == 0 else 'нет корней')
else:
return (-c / b,)
D = b**2 - 4*a*c
if D > 0:
x1 = (-b + math.sqrt(D)) / (2*a)
x2 = (-b - math.sqrt(D)) / (2*a)
return (x1, x2)
elif D == 0:
x = -b / (2*a)
return (x,)
else:
real = -b / (2*a)
imag = math.sqrt(-D) / (2*a)
return (complex(real, imag), complex(real, -imag))
Python решение примера (решение примера на python)
Функция обрабатывает все случаи: вырожденный, линейный, два действительных корня, один корень и комплексные. Возвращается кортеж корней.
Типичные ошибки:
- Забыть проверить a == 0. Без проверки деление на ноль.
- Использовать math.sqrt для отрицательного дискриминанта. Ошибка ValueError. Решение: использовать cmath.sqrt или брать корень модуля.
- Потеря точности при b2 >> 4ac. Альтернативная формула описана в расширенных примерах.
Как решить квадратное уравнение без импорта модуля math?
Оператор ** с показателем 0.5 извлекает квадратный корень, в том числе из отрицательных чисел (возвращается комплексное число).
def solve_quadratic_no_math(a, b, c):
if a == 0:
if b == 0:
return ('бесконечно много корней' if c == 0 else 'нет корней')
return (-c / b,)
D = b**2 - 4*a*c
sqrt_D = D ** 0.5
x1 = (-b + sqrt_D) / (2*a)
x2 = (-b - sqrt_D) / (2*a)
return (x1, x2)
Python вычисление значения выражений (вычисление значения выражений в python)
Подходит для минимизации зависимостей, но менее точен для комплексных корней из-за представления с плавающей точкой.
Проблема: При D, близком к нулю, могут появиться два почти равных корня. Решение: проверка abs(D) < 1e-12 и приравнивание к нулю.
Как воспользоваться библиотекой NumPy для нахождения корней?
Функция numpy.roots принимает список коэффициентов в порядке убывания степени.
import numpy as np
coeff = [a, b, c]
roots = np.roots(coeff)
вычисление функции в python (вычисление значения функции в python)
Удобно для массовых вычислений. Требует предварительной обработки случая a=0.
При a=0 и b=0 np.roots может выдать ошибку. Необходима отдельная проверка.
Как обрабатывать комплексные корни с помощью модуля cmath?
cmath.sqrt корректно извлекает корень из отрицательного числа.
import cmath
def solve_quadratic_cmath(a, b, c):
if a == 0:
if b == 0:
return ('бесконечно много корней' if c == 0 else 'нет корней')
return (-c / b,)
D = b**2 - 4*a*c
sqrt_D = cmath.sqrt(D)
x1 = (-b + sqrt_D) / (2*a)
x2 = (-b - sqrt_D) / (2*a)
return (x1, x2)
Python вычисление корня (вычисление квадратного корня в python)
Единообразный код для любого знака дискриминанта. Результат всегда комплексный.
Как решить квадратное уравнение с учётом погрешностей чисел с плавающей точкой?
Введение допуска epsilon для сравнения дискриминанта с нулём.
def solve_quadratic_eps(a, b, c, eps=1e-12):
if a == 0:
# обработка...
pass
D = b**2 - 4*a*c
if abs(D) < eps:
D = 0.0
# далее обычная логика
Позволяет избежать деления на очень малую величину. Выбор epsilon требует учёта масштаба коэффициентов.
Слишком большое epsilon может объединить близкие корни.
Продвинутые примеры решения квадратных уравнений в Python
Ниже приведены усложнённые варианты реализации, необходимые в специфических задачах численных методов.
Пример 1. Устойчивое вычисление корней при большом b
Используется альтернативная формула: сначала находится устойчивый корень, затем второй через теорему Виета.
import math
def solve_quadratic_stable(a, b, c):
if a == 0:
return (-c / b,) if b != 0 else ('беск. корней' if c == 0 else 'нет корней')
D = b*b - 4*a*c
if D < 0:
sqrt_D = complex(0, math.sqrt(-D))
x1 = (-b + sqrt_D) / (2*a)
x2 = (-b - sqrt_D) / (2*a)
return (x1, x2)
sqrt_D = math.sqrt(D)
sign = 1 if b >= 0 else -1
x1 = (-b - sign*sqrt_D) / (2*a)
x2 = c / (a * x1) if x1 != 0 else 0
return (x1, x2)
print(solve_quadratic_stable(1, 1e9, 1))
(-1e-09, -1000000000.0)
Пример 2. Символьное решение с помощью SymPy
Библиотека SymPy позволяет получить аналитическое выражение для корней.
from sympy import symbols, solve, Eq
x, a, b, c = symbols('x a b c')
equation = Eq(a*x**2 + b*x + c, 0)
sol = solve(equation, x)
sol
[(-b - sqrt(b**2 - 4*a*c))/(2*a), (-b + sqrt(b**2 - 4*a*c))/(2*a)]
Пример 3. Работа с рациональными коэффициентами (дроби)
Использование fractions.Fraction для точности при рациональных коэффициентах.
from fractions import Fraction
import math
def solve_quadratic_fraction(a_frac, b_frac, c_frac):
a = Fraction(a_frac)
b = Fraction(b_frac)
c = Fraction(c_frac)
if a == 0:
return (-c / b,) if b != 0 else ('беск. корней' if c == 0 else 'нет корней')
D = b*b - 4*a*c
sqrt_D = math.sqrt(float(D))
x1 = (-b + sqrt_D) / (2*a)
x2 = (-b - sqrt_D) / (2*a)
return (x1, x2)
print(solve_quadratic_fraction(1, 0, -4))
(2.0, -2.0)
Пример 4. Использование dataclass для организации результата
Структурированный объект с полями: корни, дискриминант, тип решения.
from dataclasses import dataclass
from typing import Union, Tuple
@dataclass
class QuadraticResult:
roots: Tuple[Union[float, complex], ...]
discriminant: float
root_type: str
def solve_quadratic_dataclass(a, b, c):
if a == 0:
if b == 0:
if c == 0:
return QuadraticResult((), 0, 'degenerate')
else:
return QuadraticResult((), 0, 'no roots')
else:
return QuadraticResult((-c/b,), 0, 'linear')
D = b*b - 4*a*c
if D >= 0:
sqrt_D = D**0.5
x1 = (-b + sqrt_D) / (2*a)
x2 = (-b - sqrt_D) / (2*a)
root_type = 'real' if D > 0 else 'double'
return QuadraticResult((x1, x2), D, root_type)
else:
sqrt_D = (-D)**0.5
real = -b / (2*a)
imag = sqrt_D / (2*a)
c1 = complex(real, imag)
c2 = complex(real, -imag)
return QuadraticResult((c1, c2), D, 'complex')
result = solve_quadratic_dataclass(1, -3, 2)
print(result)
QuadraticResult(roots=(2.0, 1.0), discriminant=1.0, root_type='real')