машинное обучение
April 25, 2022

Нахождение корня уравнения методом бисекции с Python

Математика говорит нам о том, что для непрерывной функции на отрезке a,b, таком что знаки функции на его концах разные, найдется точка: f(x)=0.
Соответственно, один из подходов нахождения решения заключается в делении отрезка пополам с сохранением условий разных знаков, пока не найдется точка или отрезок не станет, настолько мал, что в качестве решения сойдет любая его граница. Рассмотрим пример:

import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(-10, 10)

def f(x):
    return 2*x**2 - 10 

plt.plot(x, f(x))
plt.hlines(0,-10, 10)

У этом параболы есть два решения. Найдем одно из них задав интервал:

def solve_eq(f, a, b, thres=0.001):
    
    y_a = f(a)
    y_b =  f(b)
    direction = f(b) - f(a)
    
    if not y_a*y_b<0:
        print("нарушены условия разных знаков точек")
        return None
    
    dif = b-a       
    while dif>thres:
        # import pdb; pdb.set_trace()
        c = a+(b-a)/2
        y = f(c)
        if y==0:
            return c
        if y*direction > 0:
            b=c
        else:
            a = c
        dif = b-a
        
    return b
    
solve_eq(f,0, 5)           
    

Функция в цикле, пока величина интервала не стала меньше некого предела (thres), берет середину отрезка и в зависимости от знака функции в ней и знаков функции на границах (direction) заменяет либо b (знаки совпадают) либо a (знаки разные).

Проверим работу метода на примере других функций:

def f1(x):
    return x


def f2(x):
    return x**3 - 10

display(solve_eq(f1, -5, 5))
display(solve_eq(f2, 1, 4, 0.000001))