Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
SC_sem6_2012_VichMat_kw2.doc
Скачиваний:
1
Добавлен:
25.09.2019
Размер:
348.16 Кб
Скачать

1.4 Программирование

Ниже представлены листинги первой и второй программы. Файл с исходным кодом первой программы называется «dots_creator.cpp», а файл с исходным кодом второй – «approximation.cpp».

// file “dots_creator.cpp”

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

#include <vcl.h>

#include <stdio.h>

#include <stdlib.h>

#include <math.h>

#include <time.h>

#pragma hdrstop

// global variables

double disp;

// prototypes

double func(double x,int flag);

double nois(double sigma);

// functions

double func(double x, int flag)

{

double w;

int i;

w=x*x;

w=w+w*x+1/x+log10(x);

if(flag)

w+=nois(disp);

return w;

}

double nois(double sigma)

{

double s;

int j;

s=0.;

for(j=0;j<12;j++) s+=rand()/(double)RAND_MAX;

s-=6;

s*=sqrt(sigma);

return s;

}

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

#pragma argsused

int main(int argc, char* argv[])

{

FILE *fp;

double x,step,fnc;

int anr, dots,stime;

char cmd[2];

long ltime;

printf("f(x)=1/x+log10(x)+x^2+x^3\n");

printf("This function will be solved on interval from 0.1 to 1\n");

printf("How many dots do you need?: ");

while(1)

{

scanf("%d",&dots);

if(dots>0)

break;

printf("It must be a positive number. Try again: ");

}

printf("With nois? (y/n): ");

scanf("%s",cmd);

if(cmd[0]=='n' || cmd[0]=='N')

anr=0;

else

{

anr=1;

printf("Input a value of the dispersion: ");

scanf("%lf",&disp);

}

if((fp=fopen("dots.txt","wt"))==NULL)

{

printf("Failure: creating of the file was abortive\n");

return -1;

}

ltime=time(NULL);

stime=(unsigned) ltime/2;

srand(stime);

step=(1.-0.1)/dots;

fprintf(fp,"%d\n",dots);

for(x=0.1; x<1.; x+=step)

fprintf(fp,"%.16e %.16e\n", x, func(x,anr));

fclose(fp);

return 0;

}

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

// file “approximation.cpp”

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

#include <vcl.h>

#include <stdio.h>

#include <stdlib.h>

#include <math.h>

#include <conio.h>

#include <alloc.h>

#pragma hdrstop

// global variables

int flag=0;

// prototypes

double **mrx_crt(int m, int n);

void mrx_del(double **mrx_tmp,int m);

void refresh(double **tmpmas,int m,int n);

int approx(double **tmpmas,int m,double **vecA,double **vecB);

double func(double x,int num);

void outmrx(double **tmp_mrx, int m, int n);

// functions

double func(double x,int num)

{

switch(num)

{

case 0: if(x!=0.)

return 1/x;

else

flag=1;

break;

case 1: return log10(x);

case 2: return x*x;

case 3: return x*x*x;

default: break;

}

return 0.;

}

int approx(double **tmpmas,int m,double **vecA,double **vecB)

{

int i,j,k;

double W,s;

for(k=0;k<m-1;k++)

{

for(i=k+1;i<m;i++)

{

W=tmpmas[i][k]/tmpmas[k][k];

for(j=k;j<m;j++)

tmpmas[i][j] -= W*tmpmas[k][j];

vecB[i][0] -= W*vecB[k][0];

}

}

W=1.;

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

W*=tmpmas[i][i];

W=floor(fabs(W));

if(W==0.)

return 1;

for(i=m-1;i>=0;i--)

{

s=0;

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

s += tmpmas[i][j]*vecA[j][0];

vecA[i][0]=(vecB[i][0]-s)/tmpmas[i][i];

}

return 0;

}

void refresh(double **tmpmas,int m,int n)

{

int i,j;

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

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

tmpmas[i][j]=0.;

}

double **mrx_crt(int m, int n)

{

double **mrx_tmp;

int i,j;

mrx_tmp=(double **)farmalloc(m*sizeof(double *));

if(mrx_tmp!=NULL)

{

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

{

mrx_tmp[i]=(double *)farmalloc(n*sizeof(double));

if(mrx_tmp[i]==NULL)

{

for(j=i-1;j>=0;j--)

farfree(mrx_tmp[j]);

farfree(mrx_tmp);

mrx_tmp=NULL;

break;

}

}

}

return(mrx_tmp);

}

void mrx_del(double **mrx_tmp, int m)

{

int i;

if(mrx_tmp!=NULL)

{

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

if(mrx_tmp[i]!=NULL)

farfree(mrx_tmp[i]);

farfree(mrx_tmp);

}

}

void outmrx(double **tmp_mrx, int m, int n)

{

int i,j;

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

{

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

{

printf("%18.16lf",tmp_mrx[i][j]);

}

printf("\n");

}

}

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

#pragma argsused

int main(int argc, char* argv[])

{

FILE *fp;

double **buff=NULL;

double **vecA=NULL, **vecB=NULL;

double arg, fcn,sum=0.;

int m=4,k,j,dots,shift;

if((buff=mrx_crt(m,m))==NULL)

{

printf("Program failure\n");

getch();

return -1;

}

if((vecA=mrx_crt(m,1))==NULL)

{

mrx_del(buff,m);

printf("Program failure\n");

getch();

return -1;

}

refresh(vecA,m,1);

if((vecB=mrx_crt(m,1))==NULL)

{

mrx_del(buff,m);

mrx_del(vecA,m);

printf("Program failure\n");

getch();

return -1;

}

refresh(vecB,m,1);

refresh(buff,m,m);

if((fp=fopen("dots.txt","rt"))==NULL)

{

mrx_del(buff,m);

mrx_del(vecA,m);

mrx_del(vecB,m);

printf("Not found the process file\n");

getch();

return -1;

}

fseek(fp,0L,SEEK_SET);

fscanf(fp,"%d",&dots);

while(feof(fp)==0)

{

fscanf(fp,"%lf%lf",&arg,&fcn);

for(k=0;k<m;k++)

{

for(j=k;j<m;j++)

{

buff[k][j]+=func(arg,k)*func(arg,j);

if(k!=j)

buff[j][k]=buff[k][j];

}

if(flag)

break;

vecB[k][0]+=func(arg,k)*fcn;

}

if(flag)

break;

}

fclose(fp);

if(flag)

printf("Happened breakpoint: problems with computing of the function\n");

else

{

if(approx(buff,m,vecA,vecB))

{

printf("Happened breakpoint: may be too little dots or Gauss method is inapplicable for this function\n");

printf("Your sample is %d dots\n",dots);

}

else

{

printf("Sample: %d dots\n",dots);

printf("Ratios:\n");

outmrx(vecA,m,1);

}

}

mrx_del(buff,m);

mrx_del(vecA,m);

mrx_del(vecB,m);

getch();

return 0;

}

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

Первая программа построена на следующих «самостоятельных» функциях (не считая функцию main):

  • Функция double func(double x,int flag);

  • Функция double nois(double sigma).

Функция func возвращает значение функции (1.1). В качестве параметров функции нужно передавать значение аргумента и параметр flag, указывающий о необходимости зашумления значения возвращаемого результата. Зашумление будет происходить, если flag будет иметь ненулевое значение. Так как диапазон аргументов фиксирован, то в теле функции не предусмотрен возврат ошибок, связанных с вычислением значений функции.

Функция nois возвращает нормальную случайную величину с дисперсией, задаваемой sigma. Генерация случайного числа происходит с помощью генератора псевдослучайных чисел rand(), который возвращает числа с равномерным распределением. Исходное число, которое функция rand() использует для генерации последовательности, устанавливается один раз в теле main() с помощью функции srand(), которая использует для этого системное время.

В первой программе предусмотрено ветвление алгоритма рисунка 1.1, когда пользователь может решать зашумлять результат или нет. Для этого пользователь должен вводить по запросу латинскую букву y или n. Для простоты, в программе идет слежение только на отрицательный ответ, поэтому фактически для утвердительного ответа пользователь может использовать любой символ, кроме ‘n’ и ‘N’. Также предусмотрена простая защита на ввод отрицательного числа точек: если пользователь вводит отрицательное или нулевое число, то программа запросит число точек снова.

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

При удачном завершении программы, она закрывается и в каталоге с программой должен появиться файл «dots.txt». При неудачном завершении, не связанным с созданием файла, файл тоже должен появиться. При этом он может быть пуст или в нём может быть только значение числа точек. Ошибка, связанная с созданием файла, перехватывается. Функция main возвращает 0 при удачном завершении и -1 при всех перехватываемых ошибках.

Вторая программа построена на следующих «самостоятельных» функциях:

  • double **mrx_crt(int m, int n);

  • void mrx_del(double **mrx_tmp,int m);

  • void refresh(double **tmpmas,int m,int n);

  • int approx(double **tmpmas,int m,double **vecA,double **vecB);

  • double func(double x,int num);

  • void outmrx(double **tmp_mrx, int m, int n).

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

Функция mrx_crt возвращает указатель на двумерный массив размером m на n. Подразумевается, что функция вызывается корректно и параметры функции – натуральные числа. Функция выделяет память под массив в глобальной динамической памяти. В случае неудачи возвращает нулевой указатель NULL.

Функция mrx_del освобождает динамическую память, выделенную функцией mrx_crt. Функции необходимо передавать указатель на двумерный массив и количество строк этого массива. Подразумевается, что функция вызывается корректно и в её параметрах действительно указатель на двумерный массив с натуральным и реальным числом указателей на строки.

Функция refresh обнуляет все значения двумерного массива размером m на n. Подразумевается, что функция вызывается корректно и в её параметрах действительно указатель на двумерный массив с реальным размером. Функция не перехватывает ошибку, когда ей передают нулевой указатель. Необходимость данной функции обусловлена строкой «Ввод» в приведенных выше структурограммах.

Функция approx выполняет поиск параметров эмпирической формулы. Функции необходимо передавать указатель на двумерный массив формулы (1.5), количество строк массива и указатели на два вектора – vecA и vecB. Двумерный массив и свободный вектор должны быть подготовлены перед передачей согласно алгоритму рисунка 1.3. Вектор vecA специально может быть не подготовлен; именно в него запишутся параметры эмпирической формулы. Подразумевается, что функция вызывается корректно и указатели действительно на существующие массивы реального размера, так как такие ошибки не перехватываются. Данная функция целиком соответствует структурограмме рисунка 1.4. В случае удачи функция возвращает 0, а в vecA хранится результат, в противном случае функция возвращает -1. В любом случае следует помнить, что после вызова однозначно меняется структура передаваемого двумерного массива и свободного вектора.

Функция func соответствует эмпирической формуле (1.1). Функции нужно передавать аргумент и номер субфункции из (1.3). Можно передавать номера от 0 до 3, в противном случае func возвращает 0. Внутри предусмотрен перехват ошибки деления на ноль, при возникновении которой глобальная переменная flag принимает значение 1.

Функция outmrx выполняет вывод двумерного массива размером m на n. Функции передается указатель на массив и его реальные размеры. Подразумевается, что функция вызывается корректно и в неё действительно передаётся реальный указатель на массив и его реальные размеры.

Для простоты, во второй программе не предусмотрен «отлов» ошибки, когда файл пуст или в нем единственная строка. Ситуация, когда файла нет, перехватывается и выводится соответствующее сообщение. Алгоритм рисунка 1.3 выполняется внутри функции main. Функция main возвращает 0 в случае удачи и -1 при всех перехватываемых ошибках. В случае удачи на экран будут выведены параметры эмпирической формулы. Вектора в данной реализации создаются как двумерные массивы.

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