Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
МП 3,4.doc
Скачиваний:
15
Добавлен:
05.11.2018
Размер:
945.66 Кб
Скачать

Пример выполнения задания 1

Задание. Построить алгоритм для аппроксимации функции на отрезке регрессионной функцией с использованием метода наименьших квадратов. Разработать программу, реализующую этот алгоритм. Размерность равномерной сетки равна 21.

Решение. Построение алгоритма в данном случае заключается в построении системы линейных уравнений и обоснования существования и единственности решения этой системы линейных уравнений. В дальнейшем будем опираться на материал, изложенный в п.п. 4.3.

Сначала построим сетку и таблицу данных. Так как сетка равномерная и число узлов сетки равно 21, то число отрезков равно 20 (). Обозначим через шаг, который вычисляется по формуле . В нашем случае , .

Введем сетку на отрезке : . Узлы сетки находятся по формуле , . Значение находится по формуле , . Таким образом, по формуле функции на отрезке построена таблица данных размерности 21 с равномерным шагом. Отметим, что в нашем случае эта таблица является интерполяционной таблицей, так как данные не содержат погрешностей.

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

.

Используя необходимые условия экстремума функции нескольких переменных, получаем нормальную систему для определения параметров , и :

, , .

Так как функция g является линейной функцией относительно , и , то получаем систему линейных уравнений. Запишем первое уравнение:

Умножив обе части уравнения на –0.5 и преобразовав, получим:

.

Запишем это уравнение в виде:

.

Второе уравнение:

Умножив обе части уравнения на –0.5 и преобразовав, получим:

.

Запишем это уравнение в виде:

.

Третье уравнение получаем аналогично:

.

Запишем систему линейных уравнений:

Мы получили систему линейных уравнений с симметричной матрицей. Эта матрица невырожденна, так как функции линейно независимы. Следовательно, система линейных уравнений относительно неизвестных a, b и c имеет единственное решение, которое находится методом Гаусса с частичным выбором ведущего элемента.

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

Отметим, что среднеквадратичная погрешность R может принимать достаточно большие значения. Связано это с тем, что эта погрешность является абсолютной погрешностью, а не относительной, а также с тем, что регрессионная функция может быть выбрана неудачно.

Программа

#include <stdio.h>

#include <math.h>

#include <conio.h>

// Функция f(x)

float fn (float x)

{ return (pow(2,x)-3*x+4); }

// Функция g(A ,B ,C, x)

float gx (float A,float B,float C,float x)

{ return (A*sin(x)+B*x+C); }

// Функция GaussMethod - решает СЛУ размерности 3

// Входные параметры: А - матрица, В - вектор, Х - вектор неизвестных

void GaussMethod(float A[3][3],float B[3],float X[3])

{

int i,j; //счетчики циклов

// Решение системы уравнений

// k-счетчик циклов

// numb-номер строки с ведущим элементом

// max-максимальный по модулю элемент не преобразованного столбца

// str,bstr- используются при перестановке строк

// L-коэффициент преобразования

int numb=0, k;

float max, str, bstr, L;

// Прямой ход метода Гаусса

for (j=0;j<2;j++)

{

max = fabs(A[j][j]);

numb = j;

// определение максимального элемента в столбце

for (i=j;i<3;i++)

{

if (max<fabs(A[i][j]))

{ max=fabs(A[i][j]); numb=i; };

};

// если максимум - не диагональный элемент, то...

if (numb!=j)

{

// ...замена строк

for (i=0;i<3;i++)

{

str = A[numb][i];

A[numb][i] = A[j][i];

A[j][i] = str;

};

bstr = B[numb];

B[numb] = B[j];

B[j] = bstr;

};

// преобразование столбца

for (i=j+1;i<3;i++)

{

L = -(A[i][j]/A[j][j]); // вычисление коэффициента

A[i][j] = 0.0;

// обнуление элемента текущего столбца

for (k = j+1;k<3;k++) { A[i][k]=A[i][k]+A[j][k]*L; };

// и вычисление последующих в строке

B[i] = B[i]+B[j]*L;

};

};

// Обратная подстановка

for (j=2;j>=0;j--)

{

X[j] = B[j]/A[j][j];

if (j!=2)

{

for (i=2;i>j;i--) {X[j] = X[j]-A[j][i]*X[i]/A[j][j];};

};

};

}

// Главная функция

void main()

{

clrscr();

float Xi[21],Yi[21], // таблица данных

a[3][3],b[3],x[3]; // а - матрица, b - вектор,

// x - вектор неизвестных

float A=0,B=0,C=0; // искомые параметры функции g(A, B, C, x)

float h=0; // шаг

int n=20; // число отрезков - n

float ai=-2,bi=3; // отрезок [-2;3]

float R=0; // значение среднеквадратичной погрешности

h = float(bi-ai)/n; // вычисляем шаг

// Создание таблицы данных

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

{

Xi[i] = ai+i*h;

Yi[i] = fn(Xi[i]);

}

// Обнуление элементов матрицы а и вектора b

for(i=0;i<3;i++)

{

b[i] = 0;

for(int j=0;j<3;j++) { a[i][j] = 0;}

}

// Заполнение матрицы а и вектора b

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

{

a[0][0] = a[0][0] + sin(Xi[i]) * sin(Xi[i]);

a[0][1] = a[0][1] + Xi[i] * sin(Xi[i]);

a[0][2] = a[0][2] + sin(Xi[i]);

a[1][1] = a[1][1] + Xi[i] * Xi[i];

a[1][2] = a[1][2] + Xi[i];

b[0] = b[0] + Yi[i] * sin(Xi[i]);

b[1] = b[1] + Xi[i] * Yi[i];

b[2] = b[2] + Yi[i];

}

a[2][2] = n+1;

a[1][0]=a[0][1];

a[2][0]=a[0][2];

a[2][1]=a[1][2];

// Нахождение неизвестных х[3] методом Гаусса с частичным выбором

//ведущего элемента

GaussMethod(a,b,x);

A = x[0]; B = x[1]; C =x [2]; // искомые параметры A, B, C

// регрессионной функции g

// Расчет значений функции g

float Gi[21];

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

{

Gi[i] = gx(A,B,C,Xi[i]);

}

// Вычисление среднеквадратичной погрешности

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

R=R+(Yi[i]-gx(A,B,C,Xi[i]))*(Yi[i]-gx(A,B,C,Xi[i]));

R=sqrt(R/(n+1));

// Вывод значений

printf("Узлы сетки\tФункция f Регрессионная функция g\n");

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

printf(" %.2f \t %.2f \t\t %.2f \n",Xi[i],Yi[i],Gi[i]);

printf("\n\nЗначение среднеквадратичной погрешности равно : %.2g",R);

getch();

}

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]