Изучение и практическое применение методов приближения функций.

 

Постановка задачи

1. Составить программу для нахождения приближенного значения функции при заданном значении аргумента с помощью интерполяционного многочлена Лагранжа, если функция задана:

а) в не равноотстоящих узлах таблицы;

б) в равноотстоящих узлах таблицы.

2. Составить программу для вычисления приближенного значения функции при заданном значении аргумента с помощью интерполяционного многочлена Ньютона.

3. Сравнить полученные результаты выполнения заданий 1 и 2.

Вариант №13

1)  х=0,645

x

y

0,43

1,63597

0,48

1,73234

0,55

1,87686

0,62

2,03345

0,70

2,22846

0,75

2,35973

2) х=1,3862

x

y

1,375

5,04192

1,380

5,17744

1,385

5,32016

1,390

5,47069

1,395

5,62968

1,400

5,79788

Краткие теоретические сведения

Задача интерполирования функций состоит в приближенной замене функции clip_image002 более простой интерполирующей функцией clip_image004, значения которой в узлах интерполирования clip_image006 совпадают с соответствующими значениями clip_image002.

На практике чаще всего интерполируют функции clip_image002, заданные таблично, в точках clip_image009, если необходимо узнать clip_image002 при clip_image011.

Обычно clip_image004 отыскивают в виде обобщенного многочлена

clip_image014                                                               (1),

где clip_image016 - линейно независимая система функций, а clip_image018 - действительные коэффициенты, определяемые из линейной алгебраической системы:

clip_image020                                                      (2)

Пусть clip_image022. Тогда clip_image018 определяется единственным образом и clip_image004 совпадает с интерполяционным многочленом Лагранжа:

clip_image024             (3)

При вычислении коэффициентов Лагранжа разности удобно расположить следующим образом:

x-x0

x0-x1

x0-x2

...

x0-xn

x1-x0

x-x1

x1-x2

...

x1-xn

x2-x0

x2-x1

x-x2

...

x2-xn

...

...

...

...

...

xn-x0

xn-x1

xn-x2

...

x-xn

Если обозначить произведение элементов соответствующих строк через clip_image026, а произведение элементов главной диагонали - через clip_image028, то формула (3) будет иметь вид:

clip_image030                                                                                (4)

В случае равноотстоящих узлов интерполяционная формула Лагранжа имеет вид:

clip_image032                                                 (5)
где clip_image034clip_image036.

Для оценки погрешности интерполяционной формулы Лагранжа можно использовать следующее соотношение:

clip_image038                                                                              (6)

где clip_image040, clip_image042 - интервал интерполирования. Существенным недостатком интерполяции по Лагранжу является тот факт, что при известном значении многочлена clip_image044, построенного по значениям clip_image046 в точках - введение нового clip_image048 узла требует проведения всех вычислений заново. Этим недостатком не обладает многочлен интерполирования Ньютона.

Интерполяционная формула Ньютона для не равноотстоящих значений аргумента:

clip_image050
                                                                                                                                              (7)

где clip_image052 - разделенные разности m-того порядка.

Отношение clip_image054, где - называются разделенными разностями 1-го порядка.

Отношение clip_image056 - разделенными разностями 2-го порядка.

Разделенные разности m-го порядка имеют вид:

clip_image058                                                             (8)

Для равноотстоящих узлов разделенные разности m-того порядка вычисляются по формуле:

clip_image060                                                   (9)

где clip_image062 - шаг интерполирования, clip_image064.

Результаты выполнения программы

Интерполяция с помощью многочлена Лагранжа

а) с неравноотстоящими узлами

0.43 - 1.63597

0.48 - 1.73234

0.55 - 1.87686

0.62 - 2.03345

0.7 - 2.22848

0.75 - 2.35973

x=0.645

y=2.09249

б) с равноотстоящими узлами

1.375 - 5.04192

1.38 - 5.17744

1.385 - 5.32016

1.39 - 5.47069

1.395 - 5.62968

1.4 - 5.79788

x=1.3862

y=5.35555

Интерполяция с помощью многочлена Ньютона

а) с неравноотстоящими узлами

0.43 - 1.63597

0.48 - 1.73234

0.55 - 1.87686

0.62 - 2.03345

0.7 - 2.22848

0.75 - 2.35973

x=0.645

y=2.09344

б) с равноотстоящими узлами

1.375 - 5.04192

1.38 - 5.17744

1.385 - 5.32016

1.39 - 5.47069

1.395 - 5.62968

1.4 - 5.79788

x=1.3862

y=5.36743

Вывод

В ходе работы я изучил и практически применил методы приближения функций.

Текст программы

rff.h

#include <fstream.h>

#include <string.h>

#include <stdlib.h>

 

double *read_from_file(char *path, int *n)

{

 ifstream f;

 f.open(path);

 char buf[100], *ch;

 f.getline(buf, 100, '\n');

 *n=atoi(buf);

 double *table=new double[2**n];

 for (int i=0; i<*n; i++)

 {

  f.getline(buf, 100, '\n');

  ch=strchr(buf, ' ');

  *ch=0;

  ch++;

  table[i*2]=atof(buf);

  table[i*2+1]=atof(ch);

 }

 f.close();

 return table;

}

lagr.cpp

//--------------------------------------------------------------

#pragma hdrstop

#pragma argsused

//--------------------------------------------------------------

#include <iostream.h>

#include <conio.h>

#include "rff.h"

//--------------------------------------------------------------

double ravn(double *, int, double);

double not_ravn(double *, int, double);

long fact(int);

//--------------------------------------------------------------

void main()

{

 clrscr();

 cout<<"Input path to file"<<endl;

 char path[256];

 cin>>path;

 int n;

 double *f=read_from_file(path, &n);

 for (int i=0; i<n; i++)

  cout<<f[2*i]<<" - "<<f[2*i+1]<<endl;

 double x;

 cout<<"x=";

 cin>>x;

 double y;

 cout<<"[1]Equidistant nodes"<<endl;

 cout<<"[2]Not equidistant nodes"<<endl;

 char s=getch();

 if (s=='1')

  y=ravn(f, n, x);

  else y=not_ravn(f, n, x);

 cout<<"y="<<y<<endl;

 getch();

 delete f;

}

//--------------------------------------------------------------

double not_ravn(double *f, int n, double x)

{

 double *t=new double[n*n], *D=new double[n], P=1, y=0;

 for (int i=0; i<n; i++)

  for (int j=0; j<n; j++)

   t[i*n+j]=i==j? x-f[i*2]: f[i*2]-f[j*2];

 for (int i=0; i<n; i++)

 {

  D[i]=1;

  for (int j=0; j<n; j++)

   D[i]*=t[i*n+j];

  P*=t[i*n+i];

 }

 for (int i=0; i<n; i++)

  y+=f[i*2+1]/D[i];

 y*=P;

 delete t, D;

 return y;

}

//--------------------------------------------------------------

double ravn(double *f, int n, double x)

{

 double h=f[2]-f[0], t, P=1, y=0;

 t=(x-f[0])/h;

 for (int i=0; i<n; i++)

  P*=t-i;

 for (int i=0; i<n; i++)

 {

  if ((n-1-i)%2)

   y-=f[i*2+1]/((t-i)*fact(i)*fact(n-1-i));

   else y+=f[i*2+1]/((t-i)*fact(i)*fact(n-1-i));

 }

 y*=P;

 return y;

}

//--------------------------------------------------------------

long fact(int a)

{

 if (a==0)

  return 1;

 long res=1;

 for (int i=1; i<=a; i++)

  res*=i;

 return res;

}

//--------------------------------------------------------------

nyut.cpp

//--------------------------------------------------------------

#pragma hdrstop

#pragma argsused

//--------------------------------------------------------------

#include <iostream.h>

#include <conio.h>

#include "rff.h"

//--------------------------------------------------------------

double not_ravn(double *f, int n, double x);

double ravn(double *f, int n, double x);

//--------------------------------------------------------------

void main()

{

 clrscr();

 cout<<"Input path to file"<<endl;

 char path[256];

 cin>>path;

 int n;

 double *f=read_from_file(path, &n);

 for (int i=0; i<n; i++)

  cout<<f[2*i]<<" - "<<f[2*i+1]<<endl;

 double x;

 cout<<"x=";

 cin>>x;

 double y;

 cout<<"[1]Equidistant nodes"<<endl;

 cout<<"[2]Not equidistant nodes"<<endl;

 char s=getch();

 if (s=='1')

  y=ravn(f, n, x);

  else y=not_ravn(f, n, x);

 cout<<"y="<<y<<endl;

 getch();

 delete f;

}

//--------------------------------------------------------------

double not_ravn(double *f, int n, double x)

{

 double y=f[1], temp, *A=new double[(n-1)*(n-1)];

 for (int i=0; i<n-1; i++)

  A[i]=(f[(i+1)*2+1]-f[i*2+1])/(f[(i+1)*2]-f[i*2]);

 int N=n-2;

 for (int i=1; i<n-1; i++)

 {

  for (int j=0; j<N; j++)

   A[i*(n-1)+j]=(A[(i-1)*(n-1)+j+1]-A[(i-1)*(n-1)+j])/(f[(j+i*2)*2]-f[j*2]);

  N--;

 }

 for (int i=1; i<n-1; i++)

 {

  temp=1;

  for (int j=0; j<i; j++)

   temp*=x-f[j*2];

  y+=A[(i-1)*n]*temp;

 }

 delete A;

 return y;

}

//--------------------------------------------------------------

double ravn(double *f, int n, double x)

{

 double y=f[1], temp, *A=new double[(n-1)*(n-1)], h=f[2]-f[0];

 for (int i=0; i<n-1; i++)

  A[i]=(f[(i+1)*2+1]-f[i*2+1])/h;

 int N=n-2;

 for (int i=1; i<n-1; i++)

 {

  for (int j=0; j<N; j++)

   A[i*(n-1)+j]=(A[(i-1)*(n-1)+j+1]-A[(i-1)*(n-1)+j])/(i*h);

  N--;

 }

 for (int i=1; i<n-1; i++)

 {

  temp=1;

  for (int j=0; j<i; j++)

   temp*=x-f[j*2];

  y+=A[(i-1)*n]*temp;

 }

 delete A;

 return y;

}

//--------------------------------------------------------------

Предлагаю ознакомиться с аналогичными статьями: