Documente Academic
Documente Profesional
Documente Cultură
Poo-C++ - Proiect Cu Polinoame
Poo-C++ - Proiect Cu Polinoame
Proiect POO
Profesor coordonator:
Prep. Drd. Mihaița Dragan
Student:
Andrei Ciulpan
Andrei Buhai
București 2012
2
Universitatea din București
Operații cu polinoame
Profesor coordonator:
Prep. Drd. Mihaița Dragan
Student:
Andrei Ciulpan
Andrei Buhai
București 2012
Cuprins
Introducere.........................................................................................2
Cerința problemei..............................................................................4
Codul sursă.........................................................................................5
Exemplu.............................................................................................37
Bibliografie........................................................................................38
Introducere
Multă vreme C a fost limbajul preferat de programatori, în special de cei care
dezvoltau aplicații pentru sistemele MS-DOS și WINDOWS. În ultima vreme
însă, popularitatea limbajului C++ a crescut datorită faptului că permite
programarea orientată pe obiecte (Object-Oriented Programming) - o metodă de
programare folosită în prezent pentru realizarea multor aplicații software. Ideea
programării orientate pe obiecte (POO) a apărut în anii ’60, fiind pusă în
practică prin intermediul limbajelor SIMULA (1967) și SMALLTALK (1975).
Totuși, aceste limbaje au avut o răspândire relativ redusă, deoarece puțini
programatori formați la școala limbajelor clasice procedurale din acea perioadă
(FORTRAN, COBOL, PASCAL, MODULA-2, C etc.) erau dispuși să
abandoneze aceste limbaje doar de dragul de a lucra obiectual. Cu toate acestea,
în anii ’80, în urma acceptării definitive a limbajului C, un colectiv condus de
Bjarne Stroustrup, un tânăr cercetător de la Bell Lab’s, a avut ideea scrierii unui
compilator care să preia simplitatea și flexibilitatea C-ului și mecanismele de
"modelare“ ale limbajului SIMULA 67. Bjarne a numit acest dialect “C with
Classes“ și, prima versiune comercială a acestuia a apărut la AT&T în 1983, cu
denumirea modificată în cea actuală, C++ (sugerată de Rik Masciti, un
colaborator apropit a lui B. Stroustrup). Denumirea de C++ semnifică de fapt
multiplele facilităti adăugate limbajului C. Profitând de multitudinea domeniilor
de aplicație (de la grafica interactivă la proiectarea interfețelor utilizator și de la
exploatarea rețelelor de calculatoare la tehnicile de proiectare a
compilatoarelor), printre programatori în general și printre programatorii de C
în particular, aproape imediat apar partizani ai POO-ului. De ce acest succes
extraordinar ? În primul rând, din cauza faptului că limbajul C++ nu face nimic
altceva decât sa dea un nou avânt unuia dintre cele mai la modă limbaje ale
momentului (este vorba de C), iar în al doilea rând din cauza faptului că aduce o
și mai mare economie de timp în procesul de dezvoltare-implementare-testare a
aplicațiilor software. În cazul limbajelor tradiționale procedurale (3GL’s - 3rd
Generation Languages), algoritmul materializat întro diagramă de flux a datelor
(DFD - Data Flow Diagram), ajunge să se adapteze arhitecturii calculatorului.
Generația a patra de limbaje (4GL’s), cum se obișnuiește a se denumi categoria
acestor limbaje orientate pe obiecte, urmărește adaptarea calculatorului la
obiecte.
1
Principii de baza:
Avantajele POO reies din definirea principalelor concepte care stau la
baza POO și anume:
Abstractizarea – Este posibilitatea ca un program să ignore unele aspecte
ale informației pe care o manipulează, adică posibilitatea de a se concentra
asupra esențialului. Fiecare obiect în sistem are rolul unui “actor” abstract, care
poate executa acțiuni, își poate modifica și comunica starea și poate comunica
cu alte obiecte din sistem fără a dezvălui cum au fost implementate acele
facilitați. Procesele, funcțiile sau metodele pot fi de asemenea abstracte, și în
acest caz sunt necesare o varietate de tehnici pentru a extinde abstractizarea:
Încapsularea – numită și ascunderea de informații: Asigură faptul că
obiectele nu pot schimba starea internă a altor obiecte în mod direct (ci doar
prin metode puse la dispoziție de obiectul respectiv); doar metodele proprii ale
obiectului pot accesa starea acestuia. Fiecare tip de obiect expune o interfață
pentru celelalte obiecte care specifică modul cum acele obiecte pot interac ționa
cu el.
Polimorfismul – Este abilitatea de a procesa obiectele în mod diferit, în
funcție de tipul sau de clasa lor. Mai exact, este abilitatea de a redefini metode
pentru clasele derivate. De exemplu pentru o clasă Figura putem defini o
metodă arie. Dacă Cerc, Dreptunghi, etc. vor extinde clasa Figura, acestea pot
redefini metoda arie.
Moștenirea – Organizează și facilitează polimorfismul și încapsularea,
permițând definirea și crearea unor clase specializate plecând de la clase
(generale) deja definite - acestea pot împărtăși (și extinde) comportamentul lor,
fără a fi nevoie de a-l redefini. Aceasta se face de obicei prin gruparea
obiectelor în clase și prin definirea de clase ca extinderi ale unor clase existente.
Conceptul de moștenire permite construirea unor clase noi, care păstrează
caracteristicile și comportarea, deci datele și funcțiile membru, de la una sau
mai multe clase definite anterior, numite clase de bază, fiind posibilă redefinirea
sau adăugarea unor date și funcții noi. Se utilizează ideea: ”Anumite obiecte
sunt similare, dar în același timp diferite”. O clasă moștenitoare a uneia sau mai
multor clase de bază se numește clasă derivată. Esența moștenirii constă în
posibilitatea refolosirii lucrurilor care funcționează.
2
Cerința problemei
3
Codul sursă
#include <iostream>
#include <fstream>
#include <math.h>
#include <malloc.h>
#include <complex>
#include <stdlib.h>
using namespace std;
/*
1) Sa se defineasca o clasa generica pentru polinoame de o nedeterminata
cu coeficienti de un tip neprecizat ( parametru)
vezi clasa Polinom
2)
in care operatorii
=,==,operatorii aritmetici,+,-(unar si binar),*
si eventual /,%, sa fie supraincarcati pentru operatiile obijnuite cu
polinoame,
iar operatorul (tip) de conversie a tipurilor sa fie supraincarcat
pentru a efectua conversia unui obiect de tipul coeficientilor la un
polinom de grad 0 si invers.
Sirul coeficientilor unui polinom se poate reprezenta ca un vector(adica
pointer la tipul coeficientilor)
sau ca o lista simplu(dublu inlantuita la alegere).
3)
Se vor da exemple de creare si utilizare de obiecte pentru
diferite tipuri ale coeficientilor:int,float,complex dupa definirea acestui
tip ca o clasa separata),etc.
4
*/
private:
T m_coeficient;
unsigned int m_exponent;
friend class Polinom<T>;
};//class
//clasa Nod, reprezinta un nod intr-o lista dubla-inlantuita, pentru stocarea
obiectului Pereche (monom al polinomului)
template<typename T>
class Nod
{
public:
Nod(){ m_next = 0; m_prev = 0; m_pereche = 0; };
Nod* m_next; //nodul urmator
Nod* m_prev; //nodul precedent
Pereche<T>* m_pereche;//stocarea unei perechi (coef,exp)
};
6
m_real = 0;
m_imaginar = 0;
};
Complex(double real)
{
m_real = real;
m_imaginar = 0;
};
//constructor parametrizat
Complex(double real, double imaginar)
{
m_real=real;
m_imaginar = imaginar;
};
//constructor de copiere
Complex(const Complex& c)
{
m_real = 0.;
m_imaginar = 0.;
*this=c;
};
Complex& operator=(const Complex& c)
{
if(this!=&c)
{
7
m_real = c.m_real;
m_imaginar = c.m_imaginar;
}
return *this;
}
~Complex(){};
//supraincarcare operatorului de iesire <<, pentru afisarea la ecran a
numarului real
ostream& operator << (ostream& iesire)
{
iesire.precision(1);
iesire << "(" << m_real;
if( m_imaginar < 0 )
{
iesire << "-i*" << -1*m_imaginar;
}
else
{
iesire << "+i* " << m_imaginar;
}
iesire << ")";
return iesire ;
};
//supraincarcarea operatorului de intrare >>, pentru initializarea unui
numar complex
istream& operator >> (istream& intrare)
{
8
cout << "Real =" ;
cin >> m_real;
cout << "Imaginar=" ;
cin >> m_imaginar;
return intrare;
};
bool operator==(const Complex& c) const
{
if(m_real == c.m_real &&
m_imaginar == c.m_imaginar )
return true;
return false;
};
//Modulul unui numar complex z=a+bi -> z = radical(a*a + b*b);
double modul()const
{
return sqrt(m_real*m_real + m_imaginar*m_imaginar);
};
//Suma a 2 numere complexe z=a+bi si w=c+di este z+w=(a+c)+i(b+d)
Complex operator+(const Complex& numar)const
{
return Complex(m_real+numar.m_real,
m_imaginar+numar.m_imaginar);
};
Complex& operator+=(const Complex& numar)
{
m_real += numar.m_real;
9
m_imaginar += numar.m_imaginar;
return *this;
};
//Diferenta a 2 numere complexe z=a+bi si w=c+di este z-w=(a-c)+(b-d)i
Complex operator-(const Complex& numar)const
{
return Complex(m_real-numar.m_real, m_imaginar-
numar.m_imaginar);
};
10
{
double real= m_real*numar.m_real -
m_imaginar*numar.m_imaginar;
double img = m_imaginar*numar.m_real +
m_real*numar.m_imaginar;
m_real = real;
m_imaginar = img;
return *this;
};
//ridicare la putere
Complex putere(unsigned int putere)const
{
Complex rez = (*this);
unsigned int p = putere;
while(p-- > 1)
{
Complex tmp = rez * (*this);
rez = tmp;
}
return rez;
};
template<typename T>
Complex operator*(T i)const
{
return (*this) * Complex(i, 1);
};
double real()const { return m_real; };
11
double imag()const { return m_imaginar; };
template<typename T>
bool operator!=(const Complex& c, T t)
{
return !(c == t);
}
13
template<typename T>
bool operator<(const Complex& c, T t)
{
if(c.real() < (double)t && c.imag() == 0.)
return true;
return false;
}
template<typename T>
bool operator>(const Complex& c, T t)
{
return !(c < t) && !(c == t) ;
}
template<typename T>
bool operator<=(const Complex& c, T t)
{
return c < t || c == t;
}
template<typename T>
bool operator>=(const Complex& c, T t)
{
return !(c < t);
}
//////////////////////////////////////////////////////////////////////////
template<typename T>
class Polinom
14
{
public:
Polinom()
{
m_start = 0;
m_nod = 0;
};
~Polinom()
{
Sterge();
};
//constructor de copiere
Polinom(const Polinom<T>& p)
{
m_start = 0;
m_nod = 0;
*this = p;
};
//operator de copiere
Polinom<T>& operator=(const Polinom<T>& p)
{
if( p.m_nod == 0 ) return *this;
16
//avanseaza nodul
nod_p = nod_p->m_next;
nod_t = nod_t->m_next;
}
//verifica ultimul element
if(nod_p != 0 || nod_t != 0)
return false;
return true;
};
void Adauga(const Pereche<T>& p)
{
//if(p.m_coeficient == 0.) return;
//daca exista o pereche cu exponentul respectiv atunci adunam
coeficientii
Nod<T>* nod = CautaNod(p.m_exponent);
if(nod != 0)
{
Pereche<T>* gasit = nod->m_pereche;
gasit->m_coeficient += p.m_coeficient;
//sterge monomul cu coeficient zero
if(gasit->m_coeficient == (double)0.)
Verifica();
return;
}
//nu exista nici o pereche cu exponentul lui p;
//polinomul este gol ?
if(m_nod == 0)
17
{
m_start = new Nod<T>();
m_nod = new Nod<T>();
m_nod->m_pereche = new Pereche<T>(p.m_coeficient,
p.m_exponent);
m_start->m_prev = 0;
m_start->m_next = m_nod;
m_nod->m_prev = m_start;
m_nod->m_next = 0;
return ;
}
else
{
//introduce perechea in ordine crescatoare in functie de
exponent
Nod<T>* nod = m_start->m_next;
while(nod != 0)
{
Pereche<T>* pereche = nod->m_pereche;
if(p.m_exponent > pereche->m_exponent)
{
Nod<T>* adauga = new Nod<T>();
adauga->m_pereche = new
Pereche<T>(p.m_coeficient, p.m_exponent);
adauga->m_prev = nod->m_prev;
adauga->m_next = nod;
nod->m_prev->m_next = adauga ;
nod->m_prev = adauga;
18
return;
}
nod = nod->m_next;
}//while
Nod<T>* adauga = new Nod<T>();
adauga->m_pereche = new Pereche<T>(p.m_coeficient,
p.m_exponent);
adauga->m_prev = m_nod;
adauga->m_next = 0;
m_nod->m_next = adauga;
m_nod = adauga;
}
};
//verifica si sterge orice monom cu coeficientul zero
void Verifica()
{
if(m_nod == 0) return;
Nod<T>* nod = m_start->m_next;
while(nod != 0)
{
if(nod->m_pereche->m_coeficient == 0.)
{
Nod<T>* tmp = nod->m_next;
nod->m_prev->m_next = nod->m_next;
if(nod->m_next != 0)
{
nod->m_next->m_prev = nod->m_prev;
19
}
else
{
m_nod = nod->m_prev;
}
delete nod->m_pereche;
delete nod;
nod = tmp;
continue;
}
nod = nod->m_next;
}//while
};
void Sterge()
{
if(m_nod == 0) return;
while(m_nod->m_prev != 0)
{
Nod<T>* nod = m_nod;
m_nod = nod->m_prev;
delete nod->m_pereche ;
delete nod;
}
delete m_nod;
};
20
void Sterge(unsigned int exponent)
{
Nod<T>* nod = CautaNod(exponent);
if(nod == 0) return;
//stergem ultimul nod ? (caz particular)
if(nod->m_next == 0)
{
Nod<T>* end = nod->m_prev;
end->m_next = 0;
m_nod = end;
delete nod->m_pereche ;
delete nod;
return;
}
//refacem legaturile fara nodul care trebuie sters
nod->m_prev->m_next = nod->m_next;
nod->m_next->m_prev = nod->m_prev;
22
if(!primul && p->m_coeficient >= 0)
out << " + " ;
else if(p->m_coeficient < 0)
out << " - " ;
//semnul a fost afisat.
out << fabs((double) p->m_coeficient);
}
else
{
//afisare coeficient de tip: Complex
if(!primul)
cout << " + " ;
cout << p->m_coeficient;
}
if(p->m_exponent != 0)
{
out << "X";
if(p->m_exponent != 1)
out << "^" << p->m_exponent ;
}
primul = false;
nod = nod->m_next;
}
};
//calcul valoare polinom intr-un punct X
T Valoare(double X)
{
23
if(m_nod == 0) return T();
T val(0);
//polinom cu coeficienti nr. complexe
Nod<T>* nod = m_start->m_next;
while(nod != 0)
{
Pereche<T>* p = nod->m_pereche;
T coeficient = p->m_coeficient;
double exponent = p->m_exponent;
val += coeficient * ::pow(X, exponent);;
nod = nod->m_next;
}
return val;
};
Polinom<T> Suma(const Polinom<T>& p)const
{
Polinom<T> p1 = *this;
Polinom<T> p2 = p;
Polinom<T> suma;
Nod<T>* nod1 = p1.m_start->m_next;
while(nod1 != 0)
{
unsigned int exponent = nod1->m_pereche->m_exponent;
T coeficient = nod1->m_pereche->m_coeficient;
Nod<T>* nod2 = p2.CautaNod(exponent);
if(nod2 != 0)
24
{
coeficient += nod2->m_pereche->m_coeficient;
suma.Adauga(Pereche<T>(coeficient, exponent));
p2.Sterge(exponent);
}
else
{
suma.Adauga(Pereche<T>(coeficient, exponent));
}
nod1 = nod1->m_next;
}//while
Nod<T>* nod2 = p2.m_start->m_next;
while(nod2 != 0)
{
suma.Adauga( *(nod2->m_pereche) );
nod2 = nod2->m_next;
}//while
//sterge monomul cu coeficient zero
suma.Verifica();
return suma;
};//
26
//sterge monomul cu coeficient zero
diferenta.Verifica();
return diferenta;
};//
Polinom<T> Produsul(const Polinom<T>& p) const
{
Polinom<T> p1 = *this;
Polinom<T> p2 = p;
Polinom<T> produs;
Nod<T>* nod1 = p1.m_start->m_next;
while(nod1 != 0)
{
Nod<T>* nod2 = p2.m_start->m_next;
while(nod2 != 0)
{
T coef1 = nod1->m_pereche->m_coeficient;
unsigned int exp1 = nod1->m_pereche->m_exponent;
T coef2 = nod2->m_pereche->m_coeficient;
unsigned int exp2 = nod2->m_pereche->m_exponent;
Pereche<T> pereche(coef1 * coef2, exp1 + exp2);
produs.Adauga(pereche);
nod2 = nod2->m_next;
}//while
nod1 = nod1->m_next;
}//while
//sterge monomul cu coeficient zero
produs.Verifica();
27
return produs;
};//
private:
Nod<T>* CautaNod(unsigned int exponent)
{
if(m_nod == 0) return 0;
Nod<T>* nod = m_start->m_next;
while(nod != 0)
{
//daca exista un monom cu acelasi exponent, atunci intoarce
nodul
//care contine perechea respectiva
if(nod->m_pereche->m_exponent == exponent)
{
return nod;
}
//avanseaza nodul curent
nod = nod->m_next;
}//while
return 0;
};
private:
Nod<T>* m_start;//inceputul listei
Nod<T>* m_nod;//terminarea listei
};
28
template<typename T>
istream& operator >> (istream& intrare, Polinom<T>& p)
{
cout << "\n\tCate elemente va contine polinomul ? n= ";
int m = 0;
cin >> m;
int x = 0;
if(m == 0) return intrare ;
//sterge toate elementele polinomului
p.Sterge();
//intrare de la tastatura
char line[251]="\0";
//citirea polinomului de la tastatura
while(x++ < m)
{
T coeficient(0);
unsigned int exponent = 0;
cout << "\n\tCoeficient = " ;
if( p.is_complex(T()) )
{
cin >> coeficient;
}
else
{
cin >> line;
double val = atof(line);
coeficient = (T) val;
29
}
cout << "\tExponent (intreg pozitiv) = ";
cin >> exponent ;
Pereche<T> pereche(coeficient, exponent);
p.Adauga(pereche);
cout << endl;
}//while
return intrare ;
};
template<typename T>
ostream& operator << (ostream& iesire, Polinom<T>& p)
{
p.Afiseaza(iesire);
return iesire;
};
template<typename T>
Polinom<T> operator + (const Polinom<T>& p1, const Polinom<T>& p2)
{
return p1.Suma(p2);
};//
template<typename T>
Polinom<T> operator - (const Polinom<T>& p1, const Polinom<T>& p2)
{
return p1.Diferenta(p2);
};//
template<typename T>
Polinom<T> operator * (const Polinom<T>& p1, const Polinom<T>& p2)
30
{
return p1.Produsul(p2);
};//
void main()
{
//Cerinte:
//1) definirea clasei Polinom
Polinom<int> p ;
cin >> p; //citire de la tastatura prin operator de intrare >> supraincarcat
cout << "\n\tAti introdus polinomul cu forma\n";
cout << "\n\tp=";
cout << p; //afisare prin operator de iesire << supraincarcat
31
else
{
cout << "\n\tp_2 != p -> DIFERIT";
}
//Operatii obisnuite cu polinoame, prin utilizare operatorilor +, - si *
cout << "\n\tPentru executarea operatiilor de adunare,scadere,inmultire se
considera 2 polinoame de forma\n";
Polinom<float> p1;
float coef1[] = {1.f, 2.f, 5.f};
unsigned int exp1[] = {3, 2, 1};
for(int i=0; i<3; i++)
{
Pereche<float> pereche(coef1[i], exp1[i]);
p1.Adauga(pereche);
}
Polinom<float> p2;
float coef2[] = {2.f, -4.f, -4.f};
unsigned int exp2[] = {2, 1, 0};
for(int j=0; j<3; j++)
{
Pereche<float> pereche(coef2[j], exp2[j]);
p2.Adauga(pereche);
}
32
cout << "\n\tp2=";
p2 << cout;
//SUMA
cout << "\n\tSuma p1+p2=";
Polinom<float> suma = p1 + p2;
suma << cout;
//DIFERENTA
cout << "\n\tDiferenta p1-p2=";
Polinom<float> diferenta = p1 - p2;
diferenta << cout;
//PRODUS
cout << "\n\tProdusul p1*p2=";
Polinom<float> produs = p1 * p2;
produs << cout ;
//////////////////////////////////////////////////////////////////////////
cout.precision(5);
cout << fixed << produs.Valoare(x);
//////////////////////////////////////////////////////////////////////////
33
//Polinoame cu coeficienti numere complexe
cout << "\n\n\n\tPolinoame cu numere complexe:";
Polinom<Complex> pc1;
double real_1[] = {1., 2., 5.};
double imag_1[] = {1., 2., 5.};
unsigned int exp_1[] = {3, 2, 1};
for(int i=0; i<3; i++)
{
Pereche<Complex> pereche(Complex(real_1[i], imag_1[i]),
exp1[i]);
pc1.Adauga(pereche);
}
Polinom<Complex> pc2;
double real_2[] = {2.f, -4.f, -4.f};
double imag_2[] = {2.f, -4.f, -4.f};
unsigned int exp_2[] = {2, 1, 0};
for(int j=0; j<3; j++)
{
Pereche<Complex> pereche(Complex(real_2[j], imag_2[j]),
exp_2[j]);
pc2.Adauga(pereche);
}
//afiseaza cele 2 polinoame
cout << "\n\tp1=";
pc1 << cout;
cout << "\n\tp2=";
34
pc2 << cout;
//SUMA
cout << "\n\tSuma p1+p2=";
Polinom<Complex> suma_c = pc1 + pc2;
suma_c << cout;
//DIFERENTA
cout << "\n\tDiferenta p1-p2=";
Polinom<Complex> diferenta_c = pc1 - pc2;
diferenta_c << cout;
//PRODUS
cout << "\n\tProdusul p1*p2=";
Polinom<Complex> produs_c = pc1 * pc2;
produs_c << cout ;
cout << "\n\n\tCalcul valoare polinom p1*p2 in X =" ;
cin >> x;
cout << "\n\tValoare = ";
Complex c_rez = produs_c.Valoare(x);
cout << c_rez;
cout << "\n\n\n";
system("pause");
35
Exemplu
36
Bibliografie
www.wikipedia.org
www.cprogramming.com
www.learncpp.com
37