Постановка задачи
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 |
Краткие теоретические сведения
Задача интерполирования функций состоит в приближенной замене функции более простой интерполирующей функцией
, значения которой в узлах интерполирования
совпадают с соответствующими значениями
.
На практике чаще всего интерполируют функции , заданные таблично, в точках
, если необходимо узнать
при
.
Обычно отыскивают в виде обобщенного многочлена
где - линейно независимая система функций, а
- действительные коэффициенты, определяемые из линейной алгебраической системы:
Пусть . Тогда
определяется единственным образом и
совпадает с интерполяционным многочленом Лагранжа:
При вычислении коэффициентов Лагранжа разности удобно расположить следующим образом:
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 |
Если обозначить произведение элементов соответствующих строк через , а произведение элементов главной диагонали - через
, то формула (3) будет иметь вид:
В случае равноотстоящих узлов интерполяционная формула Лагранжа имеет вид:
Для оценки погрешности интерполяционной формулы Лагранжа можно использовать следующее соотношение:
где ,
- интервал интерполирования. Существенным недостатком интерполяции по Лагранжу является тот факт, что при известном значении многочлена
, построенного по значениям
в точках - введение нового
узла требует проведения всех вычислений заново. Этим недостатком не обладает многочлен интерполирования Ньютона.
Интерполяционная формула Ньютона для не равноотстоящих значений аргумента:
где - разделенные разности m-того порядка.
Отношение , где - называются разделенными разностями 1-го порядка.
Отношение - разделенными разностями 2-го порядка.
Разделенные разности m-го порядка имеют вид:
Для равноотстоящих узлов разделенные разности m-того порядка вычисляются по формуле:
Результаты выполнения программы
Интерполяция с помощью многочлена Лагранжа
а) с неравноотстоящими узлами
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;
}
//--------------------------------------------------------------
0 коммент.:
Отправить комментарий