Sunteți pe pagina 1din 15

Ministerul Educaţiei

al Republicii Moldova

Universitatea Tehnică a Moldovei

RAPORT
despre lucrarea de laborator Nr. 1
la Metode si Modele de Calcul

Tema: Rezolvarea Numerica a Ecuatiilor Algebrice si transcendente


Varianta 17

A îndeplinit: Midrigan Ovidiu

Chişinău – 2020
Mersul lucrarii:
1) Să se separe toate rădăcinile reale ale ecuației f(x)=0 unde y=f(x) este o funcție
reală de variabilă reală.
2) Să se determine o rădăcină reală a ecuaţiei date cu ajutorul metodei înjumătăţirii
intervalului cu o eroare mai mică decât ε =10 -2 .
3) Să se precizeze rădăcina obţinută cu exactitatea ε =10 -6 utilizând
- metoda aproximațiilor succesive
- metoda tangentelor (Newton)
- metoda secantelor.
4) Să se compare rezultatele luând în considerație numărul de iterații, evaluările
pentru funcția şi derivată.

Varianta 17:
a) f(x) = x3 – 18x + 43
b) f(x) = x2 + 4*sin(x)

Codul:
#include <iostream>
#include <cmath>
#include <vector>
#include <conio.h>

struct interval {
double stanga, dreapta;
double radac2, radac6;
double metAproxim, metTangentelor, metSecantelor;
};

std::vector <double> funAlgebrica;


std::vector<double> funAlgebricaderivata;
std::vector <double> sirRolle;
std::vector <interval*> intervale;
std::vector <double (*)(double x)> exempleFi;
int ordinulFunAlg;
double limitaStanga, limitaDreapta;
double a,b,c,d;
std::vector <double> derivare(const std::vector <double> fun);
std::vector <double> rezolvaFunctieGradul2(std::vector <double> fun);
void creazasirRolle();
void sortareSirRolle(std::vector <double> &fun);
int introducereFunctieAlgebrica();
double fi1X(double x);
double fi2X(double x);
double fi3X(double x);
double fi4X(double x);
double fi5X(double x);
double fi6X(double x);
double fi7X(double x);
double fi1_transX(double x);
double fi2_transX(double x);
short tipEcuatie = 0;

void inputTip();
void inputLimite();
double f(const double x);
double funDerivata(const double x);
double metInjumatatiriiIntervalului();
double metodataAproximatiilorSuccesive();
double metodaLuiNewton();
double metodataSecantelor();
int main() {
inputTip();
inputLimite();
if (tipEcuatie == 0) {
creazasirRolle();
exempleFi.insert(exempleFi.begin(), {
fi1X, fi2X, fi3X, fi4X, fi5X, fi6X, fi7X
});
}
else if (tipEcuatie == 2) {
interval *temp = new interval;
intervale.push_back(temp);
exempleFi.insert(exempleFi.begin(), {fi1_transX, fi2_transX});
intervale[0] -> stanga = limitaStanga;
intervale[0] -> dreapta = limitaDreapta;
}
metInjumatatiriiIntervalului();
metodataAproximatiilorSuccesive();
metodaLuiNewton();
metodataSecantelor();

std::cout.precision(15);
for (int i = 0; i < intervale.size(); i++) {
std::cout << std::endl << "[" << intervale[i]->stanga << ":";
std::cout << intervale[i]->dreapta << "]" << std::endl;
std::cout << "Metoda Injumatatirii : x = " << intervale[i]->radac2;
std::cout << " | R/s: " << f(intervale[i]->radac2) << std::endl;
std::cout << "Metoda Aproximarii: x = " << intervale[i]->metAproxim;
std::cout << " | R/s: " << f(intervale[i]->metAproxim) << std::endl;
std::cout << "Metoda Tangentelor x = : " << intervale[i]->metTangentelor;
std::cout << " | R/s: " << f(intervale[i]->metTangentelor) << std::endl;
std::cout << "Metoda Secantelor x = : " << intervale[i]->metSecantelor;
std::cout << " | R/s: " << f(intervale[i]->metSecantelor) << std::endl;
}
return 0;
}

std::vector <double> derivare(const std::vector <double> fun) {


std::vector <double> derivata;
int nrEls = fun.size();
int ordin = nrEls - 1;
for (int i = 0, power = ordin; i < nrEls-1; i++, power--)
derivata.push_back(fun[i] * power);
return derivata;
}

std::vector <double> rezolvaFunctieGradul2(std::vector <double> fun) {


std::vector <double> rezultate;
double delta = (fun[1]*fun[1]) - (4*fun[0]*fun[2]);
if (delta >= 0) {
if (delta > 0) {
double x1 = (-fun[1] + std::sqrt(delta)) / (fun[0] * 2);
rezultate.push_back(x1);
}
double x2 = (-fun[1] - std::sqrt(delta)) / (fun[0] * 2);
rezultate.push_back(x2);
}
return rezultate;
}
void creazasirRolle() {

funAlgebricaderivata = derivare(funAlgebrica);

std::vector <double> rezultateDeriv = rezolvaFunctieGradul2(funAlgebricaderivata);

sirRolle.push_back(limitaStanga);
for (int i = 0; i < rezultateDeriv.size(); i++) {
sirRolle.push_back(rezultateDeriv[i]);
}
sirRolle.push_back(limitaDreapta);

sortareSirRolle(sirRolle);

double y1, y2, x1, x2;


interval *temp = NULL;
for (int i = 0; i < sirRolle.size()-1; i++) {
x1 = sirRolle[i];
x2 = sirRolle[i+1];
y1 = f(x1);
y2 = f(x2);

if (std::signbit(y1) != std::signbit(y2)) {
temp = new interval;
temp -> stanga = x1;
temp -> dreapta = x2;
intervale.push_back(temp);
}
}
}
void sortareSirRolle(std::vector <double> &fun) {
double temp;
for (int i = 0; i < fun.size(); i++) {
for (int j = 0; j < fun.size()-1; j++) {
if (fun[j] > fun[j+1]) {
temp = fun[j];
fun[j] = fun[j+1];
fun[j+1] = temp;
}
}
}
}

int introducereFunctieAlgebrica() {
double temp;
ordinulFunAlg = 3;

std::cout << "Introduceti argumentele functiei de ordinul " << ordinulFunAlg <<
std::endl;
for (int i = 0; i < ordinulFunAlg+1; i++) {
std::cout << "a" << i+1 << ": ";
std::cin >> temp;
funAlgebrica.push_back(temp);
}

a = funAlgebrica[0], b = funAlgebrica[1], c = funAlgebrica[2], d = funAlgebrica[3];


std::cout << "Functia introdusa: ";
int putere = ordinulFunAlg;
for (int i = 0; i < ordinulFunAlg+1; i++, putere--) {
if (funAlgebrica[i] == 0)
continue;
else if (i != 0 && funAlgebrica[i] > 0)
std::cout << " + ";
else if (funAlgebrica[i] < 0)
std::cout << " - ";
std::cout << std::abs(funAlgebrica[i]);

if (putere > 0)
std::cout << "*x^" << putere;
}
std::cout << std::endl;
return 0;
}

double fi1X(double x) {
return -(a*x*x*x + b*x*x + (c-1)*x + c);
}

double fi2X(double x) {
return -(a*x*x + c*x + c)/(b*x);
}

double fi3X(double x) {
return -(b*x*x + c*x + d)/(a*x*x);
}
double fi4X(double x) {
return std::sqrt(-(a*x*x*x + c*x + d)/b);
}

double fi5X(double x) {
return std::cbrt( -(b*x*x + c*x + d)/a );
}

double fi6X(double x) {
return -d/(a*x*x + b*x + c);
}

double fi7X(double x) {
return std::sqrt(-(d+c*x)/(a*x+b));
}

double fi1_transX(double x) {
return sqrt(-4*sin(x));
}

double fi2_transX(double x) {
return asin((-x*x)/4);
}
void inputTip() {
int fType;
std::cout << "Alege Ecuatia\n1. Algebrica\n2. Transcendenta";
std::cout << std::endl << ">> ";
while (1) {
fType = getch();
if (fType == 49) {
std::cout << "1" << std::endl << std::endl;
introducereFunctieAlgebrica();
break;
}
else if (fType == 50) {
std::cout << "2" << std::endl;
tipEcuatie = 2;
break;
}
}
}
void inputLimite() {
std::cout << "Limita de stanga:\n>> ";
std::cin >> limitaStanga;
std::cout << "Limita de dreapta:\n>> ";
std::cin >> limitaDreapta;
}
double f(const double x) {
double y = 0;
if (tipEcuatie == 2) {
y = x*x + 4*sin(x);
}
else {
int ordin = funAlgebrica.size()-1;
for (int i = 0, power = ordin; i <= ordin; i++, power--)
y+=funAlgebrica[i]*pow(x, power);
}
return y;
}
double funDerivata(const double x) {
if (tipEcuatie == 2) {

return 2*x+4*cos(x);
}
else {
double y = 0;
int ordin = funAlgebricaderivata.size()-1;
for (int i = 0, power = ordin; i <= ordin; i++, power--)
y+=funAlgebricaderivata[i]*pow(x, power);
return y;
}
}
double metInjumatatiriiIntervalului() {
double stanga, middle, dreapta;
bool lSign, mSign, rSign;
for (int interval_nr = 0; interval_nr < intervale.size(); interval_nr++) {
stanga = intervale[interval_nr] -> stanga;
dreapta = intervale[interval_nr] -> dreapta;
while (1) {
middle = stanga + (dreapta-stanga)/2;
if (std::abs(f(middle)) < 0.01) {
intervale[interval_nr] -> radac2 = middle;
break;
}
lSign = std::signbit(f(stanga));
mSign = std::signbit(f(middle));
rSign = std::signbit(f(dreapta));
if (lSign == mSign)
stanga = middle;
else if (mSign == rSign)
dreapta = middle;
}
}
return 0;
}
double metodataAproximatiilorSuccesive() {
double xk_1, xk, stanga, dreapta;
for (int interval_nr = 0; interval_nr < intervale.size(); interval_nr++) {
stanga = intervale[interval_nr]->stanga;
dreapta = intervale[interval_nr]->dreapta;
for (int functia = 0; functia < exempleFi.size(); functia++) {
xk_1 = intervale[interval_nr]->radac2;
for (int element = 0;element < 1000;element++) {
xk = exempleFi[functia](xk_1);

if (std::isnan(xk) || xk < stanga || xk > dreapta)


break;

if (std::to_string(xk) == std::to_string(xk_1) && f(xk) < 0.000001) {


intervale[interval_nr]->metAproxim = xk;
goto doubleBreak;
}
xk_1 = xk;
}
}
doubleBreak:;
}
return 0;
}
double metodaLuiNewton() {
double xk_1, xk;
for (int interval_nr = 0; interval_nr < intervale.size(); interval_nr++) {
xk_1 = intervale[interval_nr]->radac2;
for (int i = 0;; i++) {
xk = xk_1 - f(xk_1)/funDerivata(xk_1);
if (std::abs(f(xk)) < 0.000001 ) {
intervale[interval_nr]->metTangentelor = xk;
break;
}
xk_1 = xk;
}
}
return 0;
}
double metodataSecantelor() {
double xk_1, xk, xk1;
for (int interval_nr = 0; interval_nr < intervale.size(); interval_nr++) {
xk_1 = intervale[interval_nr]->radac2;
xk = xk_1-0.0000001;
for (int i = 0;; i++) {
xk1 = xk - f(xk)*(xk-xk_1)/(f(xk)-f(xk_1));
if (std::isnan(xk1))
break;
if (std::abs(f(xk1)) < 0.000001) {
intervale[interval_nr]->metSecantelor = xk1;
break;
}
xk_1 = xk; xk = xk1;
}
}
return 0;
}
Output:
a) f(x) = x3 – 18x + 43
Alege Ecuatia
1. Algebrica
2. Transcendenta
>> 1

Introduceti argumentele functiei de ordinul 3


a1: 1
a2: 0
a3: -18
a4: 43
Functia introdusa: 1*x^3 - 18*x^1 + 43

Introduceti limitele de stanga si de dreapta


Limita de stanga:
>> -100
Limita de dreapta:
>> 100

[-100:-2.44948974278318]
Metoda Injumatatirii : x = -5.13549279086588 | R/s: -0.000950941816057593
Metoda Aproximarii: x = -5.13547727384622 | R/s: -2.54747779138143e-06
Metoda Tangentelor x = : -5.13547723222688 | R/s: -3.7294825006029e-09
Metoda Secantelor x = : -5.13547723222732 | R/s: -3.75661102225422e-09

b) f(x) = x2 + 4*sin(x)
Alege Ecuatia
1. Algebrica
2. Transcendenta
>> 2

Introduceti limitele de stanga si de dreapta


Limita de stanga:
>> -10
Limita de dreapta:
>> -1

[-10:-1]
Metoda Injumatatirii : x = -1.933837890625 | R/s: 0.000444860318459028
Metoda Aproximarii: x = 0 | R/s: 0
Metoda Tangentelor x = : -1.93375376666768 | R/s: 2.03081387262216e-08
Metoda Secantelor x = : -1.93375376667221 | R/s: 2.03321128822154e-08

Concluzie:
În aceasta lucare de laborator m-am făcut cunoscut cu metode pentru aflare radacinii
unei funcții algebrice și unei funcții transcendente și metode de aflare a intervalelor unde
se afla radacinile functiilor. Pentru aflarea rezultatelor am realizat un program în limbajul
c++.

S-ar putea să vă placă și