Как избежать выхода за пределы диапазона в цикле Python?

Рейтинг: 0Ответов: 0Опубликовано: 14.05.2023

В функции gauss_integrated() реализую расчет интеграла методом Гаусса. Надо не просто получить значение, но и уложить его в требуемую точность delta. По идее бы удваивать число интервалов, на которые дробится площадь под кривой. Но расчет завязан на коэффициенты A и t (дробим на пять - и коэффициенты берем под цифрой 5), которые я не считаю, а просто перенес из таблицы. "Пакетов" с коэффициентами всего 6 - не разбежишься. В общем я просто прибавляю по одному узлу для дробления (вместо радикального удваивания), пока не достигну шести (и если повезет - требуемой точности при этом).

Первый расчет внутренней функции gauss() (дает неточное значение) реализуется (в пункте 10 кода - строка integ_1 = gauss(n)). Но стоит прибавить единицу (и рассчитать gauss() с новым n), как получаю выход за пределы диапазона:

IndexError: list index out of range

Из диапазона выхожу в пункте 9.1 кода, в строке x_k_j = ( (b +(a*(2*j_els+1)) )/(2*(j_els+1))) + ( ( (b-a) / (2*(j_els+1)) ) * t_a_total_list[k_elems][0][0] ) . Как преодолеть ошибку?

Вот код (схематично):

import numpy as np

def func_for_integrate(x):
    """
    Исходная функция для последующего интергрирования 
    """
    res = (1+np.sqrt(x))/(x**2)
    return res

def gauss_integrated(a, b):
    """
    Функция получения интеграла по методу Гаусса 
    """
    # 1. запросим порядок формулы и точность 
    n = int( input('Введите порядок формулы (количество узлов от 1 до 6): ') )
    delta = float( input('Введите точность расчета (десятичная дробь): ') )
    
    # 2. определим условие, при котором n не может быть меньше единицы и больше шести
    assert n>=1 and n<=6, 'Определите n от 1 до 6'
    
   # 3. определим словарь с коэффициентами t:
    # здесь ключи верхнего порядка (1,2,3 и т.д.) - это n из таблицы
    # ключи второго порядка - i из таблицы,
    # значения ключей второго порядка коэффициенты t
    dict_of_koeffs_t = {
        1: 
        {1:[0]}, 
        2:
        {1:[0.57735027], 2:[-0.57735027]},
        ...
        6:
        {1:[0.932469515], 2:[0.66120939], 3:[0.23861919], 4:[-0.23861919], 5:[-0.66120939], 6:[-0.932469515]}
    }
    
    # 4. определим словарь с коэффициентами А
    dict_of_koeffs_A = {
        1: 
        {1:[2]}, 
        2:
        {1:[1], 2:[1]},
       ...
        6:
        {1:[0.17132450], 2:[0.36076158], 3:[0.46791394], 4:[0.46791394], 5:[0.36076158], 6:[0.17132450]}     
    }
    
    # 5. по заданному пользователем n извлекаем в список 
    # значения коэффициента t словаря соответствующего порядка n
    t_list = []
    for t in dict_of_koeffs_t[n].keys():
        t_list.append(dict_of_koeffs_t[n][t])
    
    # 6. по заданному пользователем n извлекаем в список 
    # значения коэффициента A словаря соответствующего порядка n
    a_list = []
    for a_els in dict_of_koeffs_A[n].keys():
        a_list.append(dict_of_koeffs_A[n][a_els])
    
    # 7. формируем список кортежей, в которых сложены соответствующие t и А:
    # первый t - первый А, второй t - второй А и т.д. 
    t_a_total_list = list(zip(t_list, a_list))

    def gauss(n):
        # 8. определим переменную для параметра j 
        j_els = n-1
    
        # 9. Рассчитаем интеграл с параметром j
        # 9.1. определим цикл для получения интеграла с параметром j
        sum_outside = 0 # первая сумма
        # Ниже диапазон: по количеству коэф-ов в зависимости от n
        # (например, при n=3 таких три: t1, t2, t3 и A1, A2, A3)
        for k_elems in range(1, n):   
            sum_inside = 0 # вторая сумма
            # i_elems - кол-во точек рассечения отрезка [a,b]
            for i_elems in range(0, j_els): 
                x_k_j = ( (b +(a*(2*j_els+1)) )/(2*(j_els+1))) + ( ( (b-a) / (2*(j_els+1)) ) * t_a_total_list[k_elems][0][0] )  
               ...
                sum_inside += ...
            sum_outside += sum_inside

        # 9.2. получим значение интеграла по формуле    
        s_j = ( ((b-a)/(2*(j_els+1))) * sum_outside )
        return s_j
    # 10. приблизим расчет по заданной пользователем точности    
    integ_1 = gauss(n)
    if n <= 5:
        n += 1
    else:
        raise Exception('Достигнуто максимальное значение параметра узлов n')
    integ_2 = gauss(n)

    # 11. применим критерий точности вычисления 
    err_gauss = abs((integ_2 - integ_1)/integ_2)

    # 12. С помощью цикла добьемся требуемой точности расчета 
    while err_gauss > delta:
        if n <= 5:
            integ_1 = integ_2
            n += 1
            integ_2 = gauss(n)
            err_gauss = abs((integ_2 - integ_1)/integ_2)
        else:
            raise Exception('Достигнуто максимальное значение параметра узлов n')
        
    # 13. Выведем результаты
    print('Интеграл по методу Гаусса: ', s_j)
    print('Достигнутая ошибка интегрирования: ', err_gauss)

    return s_j, err_gauss

gauss_integrated(1, 4)

Ответы

Ответов пока нет.