@skosterin88

Программа выдает ошибку IndexOutOfRangeException. В чем причина и как бороться?

В настоящее время я работаю над проектом, который предусматривает решение систем N уравнений с N неизвестными методом Ньютона. Есть класс "система уравнений":
public class EquationsSystem
    {
        /// <summary>
        /// Функции, определяющие внешний вид уравнений системы. Каждое уравнение имеет вид F(x1,x2,...xN) = 0.
        /// </summary>
        public List<Func<double[], double[], double>> EquationFunctions { get; set; }
        /// <summary>
        /// Коэффициенты в уравнениях системы.
        /// </summary>
        public List<double[]> EquationsCoefficients { get; set; }
    }


о ходу дела столкнулся с необходимостью решать системы из однотипных уравнений. Вот так, к примеру, выглядит сама функция, определяющая внешний вид уравнения:

static double EquationFunction(double[] x, double[] beta, int inxX)
{
            double equationValue = 0.0;

            int qVars= x.Length;

            equationValue = beta[0] + beta[1] * x[inxX] + (beta[2] / (qVars-1)) * (x.Sum() - x[inxX]);

            return equationValue;
}


А вот так выглядит фрагмент функции, где создается система уравнений:

static EquationsSystem CreateEquationsSystem(List<double[]> lstCoeffsInEquations)
        {
            int qEquations = lstCoeffsInEquations.Count;
            int qCoeffs = lstCoeffsInEquations[0].Length;

            EquationsSystem system = new EquationsSystem()
            {
                EquationFunctions = new List<Func<double[], double[], double>>(),
                EquationsCoefficients = new List<double[]>(),
            };          

            for (int i = 0; i < qEquations; i++)
            {
                system.EquationFunctions.Add(new Func<double[], double[], double>((x, beta) =>
                EquationFunction(x, beta, i));
            }      

            for (int i = 0; i < qEquations; i++)
            {
                system.EquationsCoefficients.Add(new double[qCoeffs]);
                for (int j = 0; j < qCoeffs; j++)
                {
                    system.EquationsCoefficients[i][j] = lstCoeffsInEquations[i][j];
                }
            }
            
            return system;
        }

В системе 4 уравнения, каждое из которых описывается функцией вроде приведенной выше.
При самом процессе создания системы сложностей не возникает. Но в момент, когда надо выполнить численное дифференцирование этих функций (для матрицы первых производных, которая строится на каждой итерации решения), программа впадает в ересь. Вот функция, которая выполняет вычисление производной:

public static double GetDerivative(Func<double[], double[], double> function, double[] variables, int inxVariable, double[] coefficients, double eps)
        {
            ...
            //Остальная часть не важна
            double f = function(variables, coefficients);
            ...
 
        }

На этом самом месте программа пытается вычислить значение функции и выдает ошибку IndexOutOfRangeException. Судя по данным в панели Call Stack, она снова прыгает в функцию CreateEquationsSystem() вот на это место:

...
for (int i = 0; i < qEquations; i++)
            {
                system.EquationFunctions.Add(new Func<double[], double[], double>((x, beta) =>
                EquationFunction(x, beta, i));
            }     
...
,
потом в функцию EquationFunction():
static double EquationFunction(double[] x, double[] beta, int inxX)
{
            double equationValue = 0.0;

            int qVars= x.Length;

            equationValue = beta[0] + beta[1] * x[inxX] + (beta[2] / (qVars-1)) * (x.Sum() - x[inxX]);

            return equationValue;
}

и выдает ошибку там. Учитывая, что у меня 4 уравнения, inxX по всем расчетам должен изменяться от 0 до 3 и никак иначе. Но программа считает, что в этот момент inxX там равен 4 и по этому поводу посылает меня лесом.
Соответственно, 2 вопроса:
- как так получилось?
- как решить проблему? Ведь уравнений может быть на самом деле сколько угодно, не добавлять же каждое вручную по отдельности.
  • Вопрос задан
  • 193 просмотра
Решения вопроса 1
@Maa-Kut
Очень смахивает на проблему неправильного использования замыканий. Попробуйте так:
for (int i = 0; i < qEquations; i++)
{
    int index = i;
    system.EquationFunctions.Add(new Func<double[], double[], double>((x, beta) =>
        EquationFunction(x, beta, index)); // <-- index вместо i
}
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы