Загрузка данных


import math

f = lambda x: 2 * math.log(x) - x ** 2 + 5              # уравнение f(x) = 0

SEGMENTS = [(0.01, 0.1), (2, 3)]                        # отрезки изоляции корней (по графику)
ROOTS_COUNT = 2                                         # сколько корней найти
EPSILON = 0.0001                                        # точность
PARTS = 1000                                            # на сколько частей делим отрезок (для min и max)
H = 0.0001                                              # шаг для численной производной

if ROOTS_COUNT > len(SEGMENTS):                         # ошибка, если корней запрошено больше, чем есть
    raise ValueError(f"В уравнении корней: {len(SEGMENTS)}, а запрошено {ROOTS_COUNT}")

def derivative(g):                                      # принимает функцию, возвращает её производную
    def d(x):                                           # вложенная функция: g'(x) = (g(x+H) - g(x-H)) / 2H
        return (g(x + H) - g(x - H)) / (2 * H)
    return d

PHI = [lambda x: math.exp((x ** 2 - 5) / 2),            # x = phi(x) для корня на [0.01; 0.1]
       lambda x: math.sqrt(2 * math.log(x) + 5)]        # x = phi(x) для корня на [2; 3]

for i in range(ROOTS_COUNT):                            # по одному отрезку на каждый корень
    A, B = SEGMENTS[i]                                  # границы отрезка
    phi = PHI[i]                                        # phi(x) для этого корня
    phi1 = derivative(phi)                              # производная phi'(x)

    points = [A + (B - A) * k / PARTS for k in range(PARTS + 1)]        # точки разбиения отрезка
    q = max(abs(phi1(p)) for p in points)               # q = max |phi'(x)|

    if q >= 1:                                          # при q >= 1 метод не сходится
        print(f"Корень {i + 1}: q = {q:.4f} >= 1, метод не сходится")
        continue

    x_prev = (A + B) / 2                                # начальное приближение
    iterations = 0                                      # счётчик итераций
    while True:
        x_new = phi(x_prev)                             # x(n) = phi(x(n-1))
        iterations += 1
        if q / (1 - q) * abs(x_new - x_prev) < EPSILON: # q/(1-q) * |x(n) - x(n-1)| < eps
            break
        x_prev = x_new                                  # запоминаем для следующего шага

    print(f"Корень {i + 1}: {x_new:.8f}, итераций: {iterations}, q = {q:.4f}")