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


import math

# ================== ЗДЕСЬ ЗАДАЁТСЯ УРАВНЕНИЕ ==================
def function(x):
    return 2 * math.log(x) - x ** 2 + 5      # 2*ln(x) - x^2 + 5 = 0
# ==============================================================

A = 0.01          # левая граница (ln(x) определён только при x > 0, поэтому не 0)
B = 5             # правая граница
EPSILON = 0.0001  # требуемая точность
PARTS = 1000      # на сколько кусочков делим отрезок при поиске смены знака


def find_intervals(function, a, b, parts):
    """Отделение корней: ищет кусочки отрезка, где функция меняет знак.
    Возвращает (список отрезков со сменой знака, список точных корней в узлах сетки)."""
    step = (b - a) / parts
    intervals = []
    exact_roots = []

    value_left = function(a)
    for i in range(parts):
        left = a + i * step
        right = left + step
        value_right = function(right)

        if value_left == 0:                  # левый узел сам оказался корнем
            exact_roots.append(left)
        elif value_left * value_right < 0:   # знак поменялся, значит внутри есть корень
            intervals.append((left, right))

        value_left = value_right             # правая граница станет левой на следующем шаге

    if value_left == 0:                      # последний узел (точка b) - корень
        exact_roots.append(b)

    return intervals, exact_roots


def bisection(function, left, right, epsilon):
    """Метод дихотомии на отрезке, где гарантирована смена знака.
    Возвращает (корень, количество итераций, оценка погрешности)."""
    value_left = function(left)
    previous_x = None
    iterations = 0

    while True:
        x = (left + right) / 2               # новое приближение x(n)
        value_x = function(x)
        iterations += 1

        # Проверка 1: x - точный корень
        if value_x == 0:
            return x, iterations, 0.0

        # Проверка 2: |x(n) - x(n-1)| < epsilon
        if previous_x is not None:
            difference = abs(x - previous_x)
            if difference < epsilon:
                return x, iterations, difference

        # Выбираем ту половину, где знак меняется
        if value_left * value_x < 0:
            right = x
        else:
            left = x
            value_left = value_x

        previous_x = x


# ---------- основная программа ----------
intervals, exact_roots = find_intervals(function, A, B, PARTS)

for root in exact_roots:
    print(f"Корень: {root:.8f} (точное попадание в узел сетки)")

for left, right in intervals:
    root, iterations, error = bisection(function, left, right, EPSILON)
    print(f"Корень: {root:.8f}, погрешность: {error:.2e}, итераций: {iterations}")

if not intervals and not exact_roots:
    print("Корней со сменой знака на отрезке не найдено")