Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Метод Ньютона.docx
Скачиваний:
8
Добавлен:
22.09.2019
Размер:
323.56 Кб
Скачать

Описание методики тестирования программы

Протестируем на корректное нахождение корня.

Начальная точка , параметры a=5, b=6, c=-1, погрешность вычисления 0.001.

Для каждого уравнения требуемая точность достигнута (f(x) < e).

Относительная погрешность менее 0.1%.

График и схема нахождения корня:

На каждом шаге находится касательная к точке, ее пересечение с осью дает новое значение корня.

Руководство пользователя по работе с программой.

При запуске программы предлагается выбрать номер решаемого уравнения (1-3), затем предоставляется выбор: ввести данные с клавиатуры или ввести название файла, из которого необходимо прочесть эти данные.

При вводе данных необходимо учесть, что все вводимые параметры – вещественные числа. При нарушении этого требования ввод данных необходимо повторить.

Файл с исходными данными должен иметь следующую структуру данных:

Значения x0, a, b, c, e, разделенные пробелами или знаками переноса на следующую строку.

Если файл будет не найден, ввод необходимо повторить.

После корректного ввода данных будут отображены для заданных значений:

  1. Значение найденного корня уравнения, найденного методом Ньютона и значение функции в этой точке;

  2. Точное значение корня и значение функции в этой точке;

  3. Абсолютная погрешность вычисления;

  4. Относительная погрешность вычисления.

Для каждого из 3х уравнений:

  1. ;

  2. ;

И отображены графики этих уравнений для заданных исходных данных.

Блок-схема программы

Главная программа проекта

Распечатка текста программы

main.cpp – главный элемент проекта

#include <cstdlib>

#include <iostream>

#include <graphics.h>

#include <conio.h>

# include <stdio.h>

# include <math.h>

#include <fstream>

#include "func.h"

#include "graph.h"

#include "root.h"

using namespace std;

float getFloatValue(char *label)

{//получить от пользователя числовое значение

float value;

while(1)

{

fflush(stdin);//очистка буфера

cout<<label;

if((scanf("%f",&value))==0)//если введено не число

cout<<"Tol'ko chislovoe znachenie!\n";

else break;//иначе выход из цикла

}

return value;//возращаем введеное число

}

int main()

{

float a, b, c,//коэффициенты уравнения

x0,//начальное значение

e;//погрешность

int successVubor,//успешный выбор команды меню и корректный выбор исходных значений

k;//номер уравнения

cout<<"\nVvedite nomer reshaemogo yravneniya (1-3).\n";

cin >> k;

k--;

do

{

cout<<"\nVvod dannuh:\n 1. S klaviatyru;\n 2. Iz faila;\n e. Vuhod.\n";

successVubor = 0;

char command;

cin >> command;

switch(command)

{

case '1'://ввод исходных данных с клавиатуры

x0 = getFloatValue("\nVvedite nachal'noe znachenie x0: ");

a = getFloatValue("Vvedite znachenie a: ");

b = getFloatValue("Vvedite znachenie b: ");

c = getFloatValue("Vvedite znachenie c: ");

e = getFloatValue("Vvedite pogreshnost vushisleniya e: ");

break;

case '2'://чтение данных из файла

do

{

cout<<"\nVvedite pyt' i imya faila (vuhod iz programmu: e): ";

char fileName[40];

cin>>fileName;

if(!strcmp(fileName, "e"))

exit(1);

ifstream stream(fileName, ios::in);

if(stream == NULL)

cout<<"Oshibka otkrutiya faila. Prover'te pravilnost pyti faila.";

else

{

stream>>x0>>a>>b>>c>>e;

stream.close();

break;

}

}

while(1);

break;

/*case '3'://по умолчанию

x0 = 3;

a = 12;

b = -2;

c = -1;//коэффициенты уравнения

e = 0.001;

break;*/

case 'e'://выход

exit(1);

break;

default://любая другая клавиша = неудачный выбор подменю

successVubor = 1;

}

}

while(successVubor);//пока не будет осуществлен корректный ввод исходных данных

int nSteps;//кол-во шагов при вычислении корня

//for(int k = 0; k < 3; k++)//для каждого из 3х уравнений

//{//вычисляем приближенное значение интеграла, точное значение, абсолютную и относительную погрешности

cout<<"\n\nNahodim koren' "<<(k + 1)<<" yravneniya.";

float pribl = findX(x0, a, b, c, e, k, &nSteps),

toch = getX(x0, a, b, c, k);

cout<<"\nNaidennoe znachenie: "<<pribl<<

" (f(x) = "<<f(pribl, a, b, c, k)<<

")\nTochnoe znachenie: "<<toch<<

" (f(x) = "<<f(toch, a, b, c, k)<<

")\nAbsolytnaya pogr: "<<fabs(pribl - toch);

if(toch != 0)

cout<<"\nOtnositelnaya pogr: "<<fabs((pribl - toch)) / toch * 100;

else cout<<"\nTochnoe znachenie = 0. Otnositelny'y pogreshnost' nelzya naiti.";

//}

//cout<<endl<<nSteps[0]<<" steps "<<nSteps[1]<<" "<<nSteps[2];

cout<<"\n";

system("PAUSE");

showGraphs(x0, a, b, c, nSteps, k);//отображаем графики этих уравнений

return 0;

}

root.cpp – нахождение корней уравнения

# include <math.h>

#include "func.h"

float findX(float x0, float a, float b, float c, float e, int k, int *nSteps)

{

//float ax = x1, bx = x2;

*nSteps = 0;

float lastX;

float xn = x0;

while(fabs(f(xn, a, b, c, k)) > e && *nSteps < 1000)//lastX - xn

{

*nSteps = *nSteps + 1;

lastX = xn;

if(fProizv(lastX, a, b, c, k) != 0)

xn = lastX - f(lastX, a, b, c, k) / fProizv(lastX, a, b, c, k);

else std::cout<<"\nProizvodnaya ravna 0.";

}

if(*nSteps == 1000)

std::cout<<"\nProizvedeno 1000 iteracij, trebyemaya tochnost' ne dostignyta. Vozmojno pri zadannuh ishodnuh dannuh net kornya ili ryad ne shoditsya.";

return xn;

}

float getX(float x0, float a, float b, float c, int k)

{//нахождение точного решения

switch(k)

{

case 0://решение кубического уравнения по формуле Кардано

float al, be,//альфа, бетта

p, q,//коэффициенты канонического уравнения

de;//дискриминант (дельта)

p = b / a;

q = c / a;

de = pow(p / 3, 3) + pow(q / 2, 2);

al = pow(-q / 2 + pow(de, 0.5), (float)1/3);

if(-q / 2 - pow(de, 0.5) >= 0)

be = pow(-q / 2 - pow(de, 0.5), (float)1/3);

else

be = -pow(fabs(-q / 2 - pow(de, 0.5)), (float)1/3);

if(de <= 0)

std::cout<<"\nYravnenie imeet neskol'ko deistvitelnuh kornei.";

return al + be;

case 1:

if(a != 0)

{

if(fabs(c / a) > 1)

{

std::cout<<"\nArgyment arcsin (-c/a) ne mojet but' > 1";

return 0;

}

}

else

{

std::cout<<"\nZnamenatel (a) raven 0.";

return 0;

}

return asin(-c / a) + 2 * M_PI * (int) (x0 - asin(-c / a) + b) / (2 * M_PI) - b;

case 2:

if(a != 0)

{

if (fabs(exp(-c / a) - b - x0) < fabs(-exp(-c / a) - b - x0))

return exp(-c / a) - b;

else

return -exp(-c / a) - b;

}

else

std::cout<<"Oshibka. Kornya net (a = 0)!";

return 0;

default:

return 0;

}

}

float findXWithNumber(float x0, float a, float b, float c, int step, int k)

{//получить значение х при заданном номере итерации вычисления

float lastX;

int i = 0;

float xn = x0;

while(i != step)

{

i++;

lastX = xn;

if(fProizv(x0, a, b, c, k) != 0)

xn = lastX - f(lastX, a, b, c, k) / fProizv(lastX, a, b, c, k);

}

return xn;

}

Заголовочный файл root.h

float findX(float x0, float a, float b, float c, float e, int k, int *nSteps);

float getX(float x0, float a, float b, float c, int k);

float findXWithNumber(float x0, float a, float b, float c, int step, int k);

func.cpp – вычисление значения функции и ее производной от заданного аргумента

#include <iostream>

# include <math.h>

float f(float x, float a, float b, float c, int k)

{//значение фукнции под номером k(нумерация с нуля) при аргументе x, с заданными коэффициентами a, b, c

switch(k)

{

case 0:

return a * pow(x, 3) + b * x + c;

case 1:

return a * sin(x + b) + c;

case 2:

{

if(x + b != 0)

return a * log (fabs(x + b)) + c;

else

{

std::cout<<"Oshibka. Znamenatel' prinimaet nylevoe znachenie!";

return 0;

}

}

default:

return 0;

}

}

float fProizv(float x, float a, float b, float c, int k)

{//производная функций

switch(k)

{

case 0:

return 3 * a * pow(x, 2) + b;

case 1:

return a * cos(x + b);

case 2:

if(x + b != 0)

{

if(x + b > 0)

return a / fabs(x + b);

else

return - a / fabs(x + b);

}

else

{

std::cout<<"Oshibka. Znamenatel' prinimaet nylevoe znachenie!";

return 0;

}

default:

return 0;

}

}

Заголовочный файл func.h

float f(float x, float a, float b, float c, int k);

float fProizv(float x, float a, float b, float c, int k);

graph.cpp – отображение графиков функций и процесс вычисления интеграла в графическом режиме

#include <graphics.h>

#include "root.h"

#include "func.h"

#include <iostream>

int gdriver = DETECT, gmode, errorcode;

void showGraph(float x0, float a, float b, float c, int nSteps, int k,

int miny, int maxy)

{//отображение графика одного уравнения с номером k на области от minx до miny по вертикали

int n = 30;

float x1 = findXWithNumber(x0, a, b, c, 0, k),

x2 = findXWithNumber(x0, a, b, c, 0, k);

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

{

float x = findXWithNumber(x0, a, b, c, i, k);

if(x1 > x)

x1 = x;

if(x2 < x)

x2 = x;

}

float h = (x2 - x1) / n;//ширина шага

int minx = 80,// и miny, maxy - границы области в которой нужно нарисовать график

maxx = 850;

float y1 = f(x1, a, b, c, k),//мин и макс значение функции

y2 = f(x1, a, b, c, k),

dx;

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

{//поиск мин и макс значений функции у1 и у2

float zn = f(x1 + i * h, a, b, c, k);

if(y1 > zn)

y1 = zn;

if(y2 < zn)

y2 = zn;

}

float kx, ky;//коэффициенты растяжения графика по 0х и по 0у на всю область

kx = (maxx - minx)/(x2 - x1);

ky = (maxy - miny)/(y2 - y1);

int Oy = (int)(ky * y2) + miny;//где находится ось (уравнение x=0)

int OyOtobr;//отображаемая ось

if (ky * y2 + miny > maxy)//если уравнение x=0 находится вне области отображения графика, отображаем ось внизу области

OyOtobr = maxy;

else//иначе на том уровне, где она должна быть

OyOtobr = (int)(ky * y2) + miny;

dx = kx * h;//шаг по 0х в пиксельном выражении

setcolor(WHITE);//оси белым

moveto(minx, OyOtobr);//прорисовка осей

lineto(maxx + 8, OyOtobr);

lineto(maxx + 3, OyOtobr - 5);

moveto(maxx + 8, OyOtobr);

lineto(maxx + 3, OyOtobr + 5);

moveto(minx, maxy + 3);

lineto(minx, miny - 8);

lineto(minx + 5, miny - 3);

moveto(minx, miny - 8);

lineto(minx - 5, miny - 3);

if(x1 * x2 < 0)//отображение точки (0,0), если она оказалась в отображаем области

outtextxy(minx + (int)(x1 * kx) - 3, OyOtobr + 5, "(0,0)");

char *s;

s = new char[5];

outtextxy(maxx, OyOtobr + 5, gcvt(x2, 4, s));//цены деления - мин и макс по осям

outtextxy(minx, OyOtobr + 5, gcvt(x1, 4, s));

outtextxy(5, maxy - 10, gcvt(y1, 4, s));

outtextxy(5, miny - 10, gcvt(y2, 4, s));

moveto(maxx, OyOtobr + 2);//штрихи для них

lineto(maxx, OyOtobr - 2);

moveto(minx - 3, miny);

lineto(minx + 3, miny);

moveto(minx - 3, maxy);

lineto(minx + 3, maxy);

setcolor(GREEN);//схема вычисления корня зеленым

if(y1 * y2 <= 0.2)//если есть корень на отображаемом отрезке (приблизительно)

{

float x = findXWithNumber(x0, a, b, c, 0, k);

moveto(minx + (int)((x - x1) * kx), Oy);

lineto(minx + (int)((x - x1) * kx), Oy - (int)(f(x, a, b, c, k) * ky));

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

{

x = findXWithNumber(x0, a, b, c, i, k);

lineto(minx + (int)((x - x1) * kx), Oy);

lineto(minx + (int)((x - x1) * kx), Oy - (int)(f(x, a, b, c, k) * ky));

}

}

setcolor(RED);//график красным

moveto(minx, Oy - (int)(f(x1, a, b, c, k) * ky));//встаем в начало

for(int i = 0; i <= n; i++)//и прорисовываем график

lineto(minx + (int)(dx * i), Oy - (int)(f(x1 + i * h, a, b, c, k) * ky));

}

void showGraphs(float x0, float a, float b, float c, int nSteps, int k)

{

initwindow(900, 800); //открытие окна графического режима

outtextxy(10, 5, "Graphik yravneniya:");

//outtextxy(10, 260, "Vtoroe yravnenie:");

// outtextxy(10, 520, "Tretie yravnenie:");

showGraph(x0, a, b, c, nSteps, k, 30, 700);//отображение графика первого уравнения на участке экрана от 30 до 250 пикселей сверху

//showGraph(x0, a, b, c, nSteps[1], 1, 290, 510);//отображение графика второго уравнения -//-

//showGraph(x0, a, b, c, nSteps[2], 2, 560, 770);//отображение графика третьего уравнения -//-

system("PAUSE");

closegraph();//выход из графического режима

}

Заголовочный файл graph.h

void showGraph(float x0, float a, float b, float c, int nSteps, int k,

int miny, int maxy);

void showGraphs(float x0, float a, float b, float c, int nSteps, int k);