Интерполяция почему-то рисует прямую линию - C#

Узнай цену своей работы

Формулировка задачи:

Может быть я до конца не понимаю смысл полиномов. Однако вроде я использую верные формулы для интерполяции. Собственно есть 4 метода интерполяции: Полином Лагранжа, Полином Ньютона, Кубический сплайн(alglib), линейная интерполяция. Проблему можно рассматривать на любом методе. В общем в создал я метод интерполяции
 public interface IRaschet
    {
        double Compute(double[] volt, double[] sum); 
    }
    public class Lagrange : IRaschet
    {
        double[] x;
        double[] y;    
        public double Compute(double[] volt, double[] sum)
        {
            double x0 = sum[1];
            x = sum;
            y = volt;
            double lagrangePol = 0;
            int size = 100;
            for (int i = 0; i < size; i++)
            {
                double basicsPol = 1;
                for (int j = 0; j < size; j++)
                {
                    if (j != i)
                    {
                        basicsPol *= (x0 - x[j]) / (x[i] - x[j]);
                    }
                }
                lagrangePol += basicsPol * y[i];
            }
            return lagrangePol;
        }
    }
    public class Spline : IRaschet
    {
        public double Compute(double[] volt, double[] sum)
        {
            // * x - abscissas
            // * y - vector of experimental data, straight line with small noise
            double[] x;
            double[] y;
            x = volt;
            y = sum;
            int info;
            double v;
            alglib.spline1dinterpolant s;
            alglib.spline1dfitreport rep;
            double rho;
            rho = -5.0;
            alglib.spline1dfitpenalized(x, y, 50, rho, out info, out s, out rep);
            //System.Console.WriteLine("{0}", info); // EXPECTED: 1
            v = alglib.spline1dcalc(s, 0.0);
            //System.Console.WriteLine("{0:F1", v); // EXPECTED: 0.10
            rho = +10.0;
            alglib.spline1dfitpenalized(x, y, 50, rho, out info, out s, out rep);
            //System.Console.WriteLine("{0}", info); // EXPECTED: 1
            v = alglib.spline1dcalc(s, 1.0);
            //System.Console.WriteLine("{0:F2", v); // EXPECTED: 0.969
            rho = +3.0;
            alglib.spline1dfitpenalized(x, y, 50, rho, out info, out s, out rep);
            //System.Console.WriteLine("{0}", info); // EXPECTED: 1
            //System.Console.ReadLine();
            return v;
        }
    }
    public class Newton : IRaschet
    {
        public double Compute(double[] volt, double[] sum)
        {
            double t=1;
            int n=100;
            double[] x = volt;
            double[] y = sum;
            double res = y[0], F, den;
            int i, j, k;
            for (i = 1; i <= n; i++)
            {
                F = 0;
                for (j = 0; j <= i; j++)
                {
                    den = 1;
                    for (k = 0; k <= i; k++)
                    {
                        if (k != j) den *= (x[j] - x[k]);
                    }
                    F += y[j] / den;
                }
                for (k = 0; k < i; k++) F *= (t - x[k]);
                res += F;
            }
            return res;
        }
    }
    public class Linear : IRaschet
    {
        public double Compute(double[] volt, double[] sum)
        {
            Form1 objForm1 =new Form1();
            double a;
            double b;
            double ux;
            double uxx=1;
            double mx;
            mx = 50;
            double[] mass; mass = new double[] { 1000, 2000, 3000, 4000, 5000 };
            int n = 5;
            double[] uz; uz = volt;
            double[] yz; yz = sum;
            int beg = 0;
            int end = 0;
            double Ybeg = 0;
            double Yend = 0;
            for (int i = 0; i < n - 1; i++)
            {
                if (mass[i] <= mx && mass[i] <= mx)
                {
                    beg = i;
                    end = i + 1;
                }
                Ybeg = uz[beg];
                Yend = uz[end];
                a = (Yend - Ybeg) / (mass[end] - mass[beg]);
                b = Ybeg - a * mass[beg];
                ux = a * mx + b;
                objForm1.textBox2.Text = (ux).ToString();
                Ybeg = yz[beg];
                Yend = yz[end];
                a = (Yend - Ybeg) / (mass[end] - mass[beg]);
                b = Ybeg - a * mass[beg];
                uxx = a * mx + b;
                objForm1.textBox10.Text = (uxx).ToString();           
            }
            return uxx;
        }
    }
В весь код можно не вникать. В код для расчёта полинома передаю массивы sum и volt в качестве аргументов x и y. Далее строю график с помощью zedgraph
private IRaschet Extra; 
public double[,] Pts = new double[8, 2];
        public double[] sum = new double[8];
        public double[] volt = new double[8];   
private void formSumArray()
        {
            sum[0] = Convert.ToDouble(textBox2.Text);
            sum[1] = Convert.ToDouble(textBox3.Text);
            sum[2] = Convert.ToDouble(textBox4.Text);
            sum[3] = Convert.ToDouble(textBox5.Text);
            sum[4] = Convert.ToDouble(textBox6.Text);
            sum[5] = Convert.ToDouble(textBox7.Text);
            sum[6] = Convert.ToDouble(textBox8.Text);
            sum[7] = Convert.ToDouble(textBox9.Text);
            {
                volt[0] = 0f;
                volt[1] = 1f;
                volt[2] = 2f;
                volt[3] = 3f;
                volt[4] = 4f;
                volt[5] = 5f;
                volt[6] = 6f;
                volt[7] = 6.2f;
            }
            for (int a = 0; a < volt.Length; a++)
            {
                Pts[a, 0] = volt[a];
                Pts[a, 1] = sum[a];
            }
        }  
private void button3_Click(object sender, EventArgs e)
        {
                // ВЫЗЫВАЕТЕ МЕТОД COMPUTE
                formSumArray();
                GraphPane pane = zedGraphControl1.GraphPane; 
                GraphControl("Величина", "Напряжение", "График"); // для первого вызова
                // Создадим список точек
                PointPairList list = new PointPairList();
                double xmin = 0;
                double xmax = 10;
                // Заполняем список точек
                for (double x = xmin; x <= xmax; x += 0.01)
                {
                    // добавим в список точку
                    list.Add(x, Extra.Compute(volt, sum));
                }
                // Создадим кривую с названием "Sinc", 
                // которая будет рисоваться голубым цветом (Color.Blue),
                // Опорные точки выделяться не будут (SymbolType.None)
                LineItem myCurve = pane.AddCurve("Sinc", list, Color.Blue, SymbolType.None);
                // Вызываем метод AxisChange (), чтобы обновить данные об осях. 
                // В противном случае на рисунке будет показана только часть графика, 
                // которая умещается в интервалы по осям, установленные по умолчанию
                zedGraphControl1.AxisChange();
                // Обновляем график
                zedGraphControl1.Invalidate();
        }
Что то обсчитывается , массивы заполняются, лист точек заполняется. Вроде что-то работает. НО график строится прямая горизонтальная линия. Такого быть не может, должна какая то кривая получиться. И еще почему, если задать n=больше 8 (количество промежуточных точек нужно 100), то программа крашится и говорит что индекс лежит не в пределах массива. Так как я задаю 8 точек, то логично, что между ними мне нужно вычислить 100 промежуточных и построить график.
Наверное я как-то неправильно работаю с zedgraph, кто из знающих может увидеть ошибку?

Решение задачи: «Интерполяция почему-то рисует прямую линию»

textual
Листинг программы
public class Lagrange : IRaschet
    {
        double[] x;
        double[] y;    
        public double Compute(double x, double[] volt, double[] sum) //нужно будет изменить интерфейс
        {
            double x0 = x; //точка, в которой нужно найти значение функции
            x = sum; //массив известных X, не уверен, что тут правильно написано, что sum, а что volt
            y = volt; //массив известных Y
            double lagrangePol = 0;
            int size = volt.Length; // размер массивов
            for (int i = 0; i < size; i++)
            {
                double basicsPol = 1;
                for (int j = 0; j < size; j++)
                {
                    if (j != i)
                    {
                        basicsPol *= (x0 - x[j]) / (x[i] - x[j]);
                    }
                }
                lagrangePol += basicsPol * y[i];
            }
            return lagrangePol;//значение функции в данной точке X.
        }
    }

ИИ поможет Вам:


  • решить любую задачу по программированию
  • объяснить код
  • расставить комментарии в коде
  • и т.д
Попробуйте бесплатно

Оцени полезность:

11   голосов , оценка 4.091 из 5
Похожие ответы