Documente Academic
Documente Profesional
Documente Cultură
1.
Notiunea de algoritm
2.
3.
4.
5.
2.
6.
2.
7.
8.
9.
10.
11.
1.
L1. Notiunea de algoritm
Istoric. Definitie
Cuvantul algoritm provine de la numele unui matematician arab (Mohammed ibn-Musa al-Khowarizmi) a carui lucrari au fost
traduse in latina sub numele de Algoritmus.
Definitia actuala a cuvantului algoritm :
Ansamblu de simboluri folosite n matematic i n logic, permind gsirea n mod mecanic (prin calcul) a unor
rezultate.
Din punctul de vederea al informaticii, algoritmul reprezinta rezolvarea etapizata, in pasi mici, elementari, a unei probleme.
Scopul folosirii algoritmului este aplicarea lui la o serie pe probleme care au aceeasi metoda de rezolvare; adica, pentru orice
dateale problemei, algortimul trebuie sa se incheie cu un raspuns.
Un exemplu in acest sens este acuatia de gradul I. Exista o infinitate de ecuatii de gradul I dar toate se subscriu aceleiasi ecuatii
generice A*X+B=0. Algoritmul trebuie sa rezolve aceasta ecuatie generica pentru a obtine rezultate corecte pentru intreaga clasa
se ecuatii de gradul I sau sa anunte eroarea in cazul in care simbolul A ar avea valoarea 0.
Caracteristici
Deducem de aici o serie de proprietati pe care un algoritm corect trebuie sa le indeplineasca:
sa aiba caracter de generalitate: sa rezolve o intreaga clasa de probleme de acelasi gen (pentru orice date de intrare)
sa aiba finitudine: sa ofere un raspuns la problema si sa se incheie in timp util
sa fie clar: calculul/etapele sa fie descriese intr-o maniera fara dubii
DATE DE INTRARE -> ALGORITM -> DATE DE IESIRE
Reprezentarea algoritmilor
S-au identificat cateva structuri folosite in descrierea unui algoritm:
De asemeni, pentru exprimarea algoritmilor s-au incercat metode care sa poata fi intelese de toti. Iata cateve dintre ele:
scheme logice: metoda grafica care specifica traseul ce trebuie urmat
pseudocod: un set de reguli de scriere , in principiu in limba engleza; pt elevi s-a simplificat, folosindu-se aceleasi notatii
si limba romana (o varianta care se poate folosi in laborator gasiti la http://www.haskell.org/haskellwiki/Rodin/Download)
limbaj de programare: mult mai strict ca exprimare dar folosind aceleasi concepte.
Programul principal
{ instr; }
Instructiuni de citire/afisare
citeste variabila;
scrie expresie;
text . text;
Atribuirea
Operatori logici:
SAU, SI,
Instructiune de test
Instructiuni repetitive
2.
L2. Pseudocod. Date. Expresii
Cuvantul pseudocod provine din pseudo, care inseamna fals, si cod care se refera la textul scris intr-un limbaj de programare.
Deci pseudocod inseamna un asa-zis limbaj de programare.
Pseudocodul foloseste aceeasi operatori si o exprimare la relaxata fata de un limbaj consacrat , care cere rigurozitate.
Pseudocodul, ca orice limbaj, foloseste date, variabile, operatii si instructiuni.
Pentru doritori, va prezint o varianta de pseudocod apropiata de cea din manual, limbajul Rodin a domnului profesor Dan Popa de
la Univeristatea Bacau. In acest fel puteti pigmenta orele de informatica din clasa a 9-a si cu ore de laborator. :)
Date
Datele cu care lucreaza un algoritm (scris in pseudocod) sunt:
Variabile
O variabila este un simbol care se caracterizeaza prin:
nume; se noteaza cu combinatii de litere sau cifre dar intotdeauna primul caracter este litera: a, Beta, nr1, nr2
tip de data: intreg, real, sir de caractere, logic
valoare: functie de tipul de data asociat, o variabila poate avea valori din cele de mai sus; valoarea memorata se poate
schimba, de unde si numele de variabila;
Practic, o variabila se comporta ca o cutie ce poate fi folosita doar pentru ceva anume: valorile intregi in cutii pentru valori intregi si
valori reale in cutii pentru valori reale; doar nu puneti zahar intr-o cutie de pantofi. :).
Din acest motiv, la inceputul algoritmului nostru in pseudocod trebuie sa specificam cu ce variabile lucram si ce tip au, ca in
exemplul de mai jos:
intreg m,n
real x,y.z
logic ok, exista, este
Expresii
Expresiile sunt foormate din operatori si operanzi. Formeaza expresie urmatoarele
o variabila
variabila operator variabila
expresie operator expresie
operator expresie (cazul operatorilor unari de genul - (5+3) )
Dintre operatorii folositi vom vorbi acum numai de cei intregi (care se folosesc numai pentru operanzi intregi):
semnul - se foloseste pentru scaderi sau ca operator unar
semnul + se foloseste pentru adunari
semnul * se foloseste pentru inmultiri
semnul / se foloseste pentru impartiri
semnul % se foloseste pentru a obtine restul impartirii primului operand la cel de al doilea
o
a % b = restul impartirii lui a la b
o
a % 2 = restul impartirii lui a la 2, care este 1 daca a este impar si 0 daca a este par
o
a % 10 = restul impartirii lui a la 10, care este intotdeauna ultima cifra a lui a, cifra unitatilor
prioritatea operatiilor este aceeasi ca in matematica; mai intai inmultirile si impartirile si apoi adunarile si scaderile
se pot folosi si paranteze pentru expresiile mai complicate, dar numai perechide paranteze rotunde
atentie la ordinea operatiilor si folosirea parantezelor rotunde (ex. ecuatia de gradul 2):
o
x1=-b+ radical(b*b-4*a*c)/2*a
o
x1=(-b+ radical(b*b-4*a*c))/2*a
o
x1=(-b+ radical(b*b-4*a*c))/(2*a)
3.
L3. Instruciuni intrare/ieire. Atribuirea
Instructiuni de intrare ieire
Asa cum am vazut in lectiile anterioare schema fluxului de date in rezolvarea unei probleme este urmatoarea:
Date de intrare -> Algoritm -> Date de iesire (Rezultate)
Deducem ca aven nevoie de o metoda de a prelua datele initiale (ale problemei reale) pentru a le putea prelucra in algoritm. De
asemenea, avem nevoie de o metoda de a transmite rezultatul calculului nostru.
Pentru preluarea datelor vom folosi instructiunea Citeste.
Sintaxa: Citeste variabila;
Exemplu: Citeste a;
Efect: Se citeste o valoarea care va fi memorata in variabila a
Observatii:
o
pentru intreg n; citeste n , nu putem introduce o valoare reala (3.14) deoarece variabila n este declarata ca
fiind intreaga
Observatii
o
pentruafisarea unor texte folosim text acesta este mesajul
instructiunea scrie afiseaza valoarea expresiei; atunci o instructiune de tipul Scrie a+b va afisa valoarea
calculata a expresiei a+b; adica se aduna valoarea lui a cu valoarea lui b si se afiseaza rezultatul expresiei
Pana acum, cel mai complicat algoritm pe care il putem scrie este cel de adunare a doua valori intregi:
Intreg a, b;
Citeste a, b;
Scrie a+b.
Daca ar fi doar atat :P
Atribuirea
Pentru a schimba valoarea unei variabile pot folosi citirea. Daca totusi doresc ca variabila sa primeasca valoarea unei expresii
calculate pe parcursul algoritmului, atunci am nevoie de atribuire:
o
o
o
o
o
noua valoare se memoreaza peste vechea valoare care se va pierde; adica, se inloceste vechea valoare cu cea noua
in fiecare din exemple in variabila se memoreaza o valoare de acelasi tip cu variabila; nu putem memora intr-o variabila o valoare de alt tip:
o
o
secventa intreg a; a<-3.14; scrie a; nu este corecta; variabila a este de tip intreg si nu poate memora o valoare reala.
secventa real a; a<- +10; este corecta deoarece valoarea intreaga 10 este si valoare reala, conform incluziunii matematice.
greselile frecvente sunt cele in care valori obtinute in urma unor impartiri sau radicali (valori reale) sunt atribuite unor variabile intregi
operatiile cele mai de intalnite la atribuire sunt incrementarea (marirea cu 1 a valorii variabilei) si decrementarea (micsorarea cu 1 a valorii variabilei)
incrementarea: a<- a+1;
asa cum stim , intai se calculeaza valaorea expresiei (cresterea cu 1 a lui a) si apoi se memoreaza in variabila, peste vechea valoare
decrementarea: a<- a-1;
se calculeaza valoarea expresiei (scadereacu 1 a lui a) si apoi se memoreaza in variabila, peste vechea valoare
Exemplul 1: calculul vitezei, atunci cand stim valoarea distantei parcurse si timpul necesar;
real viteza;
intreg timp, distanta;
citeste timp, distanta;
viteza <- distanta/timp;
scrie viteza.
Exemplul 2 (interschimbarea a doua variabile folosind auxiliar). Fie doua variabile intregi. Sa se interschimbe valorile
variabilelor. Daca variabila a are valoarea 5 si variabila b are valoarea 7, dupa executarea algorimului, variabila a sa aiba valoare 7
si variabila b sa aiba valoare 5.
intreg a, b, aux;
citesc a, b;
aux<-a;
a<-b;
b<-aux;
scrie a, b.
observatie: problema este similara cu urmatoarea problema. Aveti un pahar de bere (rolul variabilei a) si o halba de suc
(rolul variabilei b). Pentru a schimba bauturile aveti nevoie de o cana goala (rolul variabilei aux);
o
turnam in cana goala continutul paharului
o
turnam in pahar continutul halbei
o
turnam in halba continutul canii
o
acum toate sunt in ordine; berea in halba si sucul in pahar si gana este goala; NU BEM DECAT SUCUL!
Exemplul 2 (interschimbarea valorii a doua variabile fara auxiliar). Avem aceeasi problema dar trebuie rezolvata fara o
variabila in plus.
intreg a, b;
citeste a,b;
a <- a+b; b<- a-b; a<- a-b;
scrie a,b.
4.
L4. Instruciunea de decizie
Fara instructiunea de decizie sau de test (in nici un caz detest) algorimul ar fi linear. Aceasta instructiune ne ajuta in cazul in care
avem o intrebare privind natura datelor folosite, a valorii lor la un moment dat.
Practic, trebuie sa punem intrebari la care algoritmul sa raspunda cu adevarat/fals; ce operatori folosim pentru a obtine raspunsuri
adevarat/fals?
o
o
o
o
o
o
Operatori logici
Operatorii logici (cu care lucreaza si logica matematica) sunt SI, SAU si NEGARE:
Operatorul SI este un operator binar, cu doi operanzi cu valoare logica. Rezultatul operatorului SI este adevarat numai
daca ambii operanzi au valoarea ADEVARAT.
o
Mie imi place fata bruneta si cu ochi albastri!
o
daca fata nu este bruneta sau nu are ochi albastri nici nu ma uit la ea (:P), ceea ce inseamna fals; daca macar
una dintre conditii este falsa atunci intreaga expresie este falsa
Operatorul SAU este un operator binar cu doi operanzi cu valoare logica. Rezultatul operatiei SAU este adevarat daca
macar unul din operanzi are valoarea ADEVARAT.
o
Mie imi place fata bruneta SAU cu ochi albastri!
o
Fata nu trebuie sa aiba ambele calitati. Daca este bruneta imi place (ADEVARAT). Daca este cu ochi albastri imi
place (ADEVARAT).
o
Daca macar una din conditii este adevarata atunci intreaga expresie este adevarata
Operatorul de negatie (vom folosi semnul ! ) schimba valoarea de adevar a expresiei: !ADEVARAT==FALS si !FALS
==ADEVARAT
Exemple:
X apartine [-5, -2]
o
(x>=-5) SI (X<=-2)
x nu apartine (-7,9]
o
(x<=-7) SAU (x>9)
o
!(x>-7) SAU !(x<=9)
o
!((X>-7) SI (x<=9))
Observatii
prioritatea operatorilor logici: negare, SI, SAU
in cazul expresiilor logice se pot aplica regulile lui De Morgan:
o
o
Pentru ca pdeudocodul nu este un limbaj in sine ci doar o conventie de notatii, sugerez sa folosim deja notatiile din C++;
cand o secventa de instructiuni trebuie executate una dupa alta, datorita logicii algoritmului, acea secventa o vom incadra
in acolade (de exemplu: {instructiune1; instructiune2; instructiune3; }); vom reveni cu amanunte.
Exemple:
Sa se afiseze maximul a doua valori citite.
intreg a,b;
citeste a,b;
daca (a>b) atunci scrie a
altfel scrie b.
Sa se afiseze modulul (matematic) al unui numar intreg.
intreg a;
citeste a;
daca (a>0) atunci scrie a
altfel scrie -a.
Sa memoram valoarea maxima intr-o variabila si sa o afisam.
intreg a,b,max;
citeste a,b;
daca (a>b) atunci max<-a
altfel max<-b;
Scrie max.
Sa se citeasca o valoare intreaga si sa se stabileasca daca s-a citit o valoare para sau nu.
intreg a;
citeste a;
daca (a%2 ==0) atunci scrie Valoarea citita este para!
intreg a,b;
real x;
citeste a,b;
daca (a!=0) atunci { x<- -b/a; scrie Solutia ecuatiei este ; Scrie x;}
altfel scrie Nu se poate calcula solutia ecuatiei.
Secventa { x=-b/a; scrie Solutia ecuatiei este ; Scrie x;} trebuie gandita ca un intreg deoarece este valabila numai pentru cazul in
care a este nenul; de aceea am incadrat-o intre acolade.
Fie a, b si c coeficientii unei ecuatii de grad 2 (a*x^2+b*x+c=0). Sa se calculeze valorile radacinii, daca exista.
o
conditia pentru a fi ecuatie de grad 2: coeficientul a trebuie sa fie nenul (a!=0)
o
trebuie calculata valoarea DELTA=b*b-4*a*c
o
pentru a avea solutii, valoarea DELTA trebuie sa fie pozitiva, cel putin nula;
o
vom folosi radical (expr) pentru a calcula valoarea radicalului unei expresii reale/intregi
intreg a,b,c,delta;
real x1,x2;
citeste a,b,c;
daca (a==0) atunci scrie Coeficientii nu formeaza ecuatie de gradul 2;
altfel {delta=b*b-4*a*c;
daca (delta<0) atunci scrie Nu se pot calcula radacini reale
altfel {x1<- (-b+radical(delta))/(2*a); x2<- -b-radical(delta))/(2*a);
scrie Solutiile sunt :, x1, , x2; }
}
Observatii:
x1 si x2 sunt declarati reali pentru ca se obtin in urma radicalului si a unei impartiri
urmariti daca algoritmul scrie concide cu termenii problemei
pentru cazul coeficientului a nenul trebuie efectuate doua operatii (calculul lui delta si testul lui delta), motiv pentru care
acestea au fost incadrate intre acolade
de asemenea, aici au trebuit puse acolade pentru calculul celor doua solutii si a afisarii solutiilor
Fie o functie matematica data pe intervale. Sa se calculeze valoarea functiei intr-un punct x oarecare daca expresia
functiei este:
o
x^2+2*x+1 daca x<0
o
3*x+5 daca x apartine [0,5)
o
-x+2 daca x>=5
o
este clar ca valoarea functie difera pe cele trei intervale; va trebui sa verificam, pe rand, carui interval apartine
valoarea citita pentru x;
real x,f;
citeste x;
daca (x<0) atunci f<- x*x+2*x+1
altfel daca (x>=5) atunci f<- -x+2
altfel f<- 3*x+5;
scrie f.
5.
L5. Instruciunea repetitiv CT TIMP
Chiar si cu atribuirea si intructiunea de decizie, si tot nu este de ajuns. Exista probleme ce necesita repetarea unor operatii si cu
ceea ce stim, nu putem face fata.
Exista trei instructiuni (structuri) repetitive folosite in toate limbajele:
instructiunea repetitiva cu test initial CAT TIMP (WHILE) (se foloseste cand numarul de repetitii este nedefinit)
instructiunea repetitiva cu test final REPETA-PANA CAND / EXECUTA CAT TIMP (DO WHILE sau REPEAT) (se foloseste
cand numarul de repetitii este nedefinit)
instructiunea repetitiva cu un numar cunoscut de pasi PENTRU (FOR) (se foloseste cand numarul de repetitii
este cunoscut)
Observatii:
CAT TIMP este repetitiva conditionata anterior deoarece intai se evaluaeza conditia si apoi se executa instructiunea
Practic, succesiunea de etape este exp logica, instructiune,exp logica, instructiune,exp logica,instructiune,exp
logica;succesiunea se incheie cu exp logica in momentul in care valoarea expresiei este FALS.
daca pe cazul ADEVARAT trebuie sa scriem mai multe instructiuni, acestea vor fi grupate cu acolade
Exemplul 1
Fie a si b doua valori naturale. Se se simuleze inmultirea a*b prin adunari repetate.
o
P=a*b=a+a+.+a de b ori
o
Expresia de mai sus spune ca a trebuie adunat la P de b ori; adica, la fiecare adunare la P a lui a putem sa
scadem un 1 din b (decrementam), pentru a pastra numarul de adunari ce mai trebuie efectuat; candb va fi zero , se va
adunat a de b ori
intreg a,b,p;
citeste a,b;
p<-0;
cat timp (b>0) executa {p<- p+a; b<- b-1;};
scrie p.
Observatii:
pentru fiecare adunare a lui a la p, scadem un 1 din b
aceste operatii trebuie executate pentru fiecare caz in care b este pozitiv; de aceea au fost grupate cu acolade
este algoritmul corect? Sa verificam cazurile cu zero:
o
daca a este zero, atunci la P se aduna zero de b ori; practic P ramane la valoarea zero. CORECT!
o
daca b este zero, conditia din CAT TIMP este falsa si atunci nu se executa instructiunile; in consecinta se
afiseaza direct valoarea lui P,adica zero; CORECT!
Exemplul 2
Fie a si b doua valori naturale. Sa se simuleze impartirea lui a la b prin scaderi repetate si sa se afiseze catul si restul.
o
vom scadea din a valoarea lui b de mai multe ori, numarand intr-o variabila contor de cate ori am facut scaderea
(practic variabila contor va fi catul impartirii)
o
operatia se va repeta cat timp din a se mai poate scadea un b, adica cat timp a mai mare decat b
o
Ce reprezinta valoarea ramasa in a? O valoare mai mica decat b? Evident, restul impartirii.
intreg a, b, contor;
contor<- 0;
daca (b=0) atunci scrie nu se realizeaza impartiri la zero!;
altfel {cat timp (a>=b) executa {a<- a-b; contor<-contor+1;};
scrie catul este , contor;
scrie restul este , a;
}.
Observatii:
am pus intre acolade secventa in care numaram de cate ori am scazut pe b din a; erau doua instructiuni;
este corect algoritmul? Daca incercati cazurile normale, va merge. Sa verificam cazurile speciale:
o
daca a este mai mic decat b atunci cat timp nu va functiona si se va afisa direct contor (zero) si a(restul);
CORECT!
o
daca a este zero, atunci nu se executa cat timp si se afiseaza contor si a (0 si 0 ) CORECT!
o
daca b este zero, se afiseaza mesajul de eroare si algoritmul se incheie CORECT!
Exemplul 3.
Sa se calculeze cel mai mare divizor comun a doua valori a si b naturale.
o
asa cum spune definitia, cel mai mare divizor comun trebuie sa fie o valoare, care sa divida atat pe a cat si pe b;
aceasta valoare poate fi in cel mai bun caz a sau b
intreg a,b;
citeste a,b;
cmmdc<- a;
cat timp (a%cmmdc +b%cmmdc !=0) executa cmmdc<- cmmdc-1;
scrie cmmdc.
Observatii:
expresia a%cmmdc +b%cmmdc !=0 este nula doar daca atat a%cmmdc cat si b%cmmdc sunt nule, adica cmmdc divide
simultan a si b; atat timp cat aceasta conditie nu se realizeaza scadem cmmdc-ul
ultima valoare panaa la care se poate scadea este 1, divizorul tuturor numerelor; in acest caz a si b se numesc numere
prime intre ele.
Exemplul 4
Ghiceste-mi numarul! Eu imi aleg un numar intre 1 si 100. In cati pasi il poti ghici? La fiecare incercare raspund cu
SUCCES, MIC sau MARE.
o
prima varianta este sa intrebam aleator; cam multi pasi!
o
sa parcugem valorile de la 1 la 100; cam multi pasi!
sa gandim! vom testa intodeauna mijlocul intervalului; in acest fel, la fiecare intrebare, elimin jumatate din cazuri.
Exemplul 5.
Fie N un numar natural. Sa se calculeze suma cifrelor lui N.
o
vom initializa o variabila suma cu zero
o
trebuie ca delimitam pe rand cifrele care formeaza numarul N; putem determina rapid ultima cifra: n%10; daca o
stergem (n<- n/10) putem deternima penultima cifra; s.a.m.d.
o
cand ne oprim? cand N nu mai are cifre; deci , cand N este zero.
intreg n, suma;
citeste n;
suma <-0;
cat timp (n!=0) executa {suma<-suma+n%10; n<-n/10;};
scrie suma.
Observatie:
instructiunea suma<-suma+n%10 creste suma cifrelor deja obtinute cu valoarea ultimei cifre a lui n.
pentru cazul in care n este nul, cat timp nu se mai executa si se afiseza suma cu valoarea 0; Suma cifrelor lui 0 este 0.
CORECT!
5.1
L9. Algoritmi fundamentali. iruri de numere
Pentru a prelucra un sir de numere trebuie sa stim fie numarul de valori in discutie (sir cu numar cunoscut de valori), fie sa avem o
valoare care sa marcheze sfarsitul sirului (de obicei zero).
natural x, n, i;
citeste N
pentru i=1,N executa
{
citeste X;
//prelucrez X
........
}
citeste x;
cat timp (x!=0) {
//prelucrez valorea X
.........
//trec la valoarea urmatoare
citeste X
}
Probleme
1.
2.
3.
4.
5.
Presupunand ca sirul reprezinta coeficientii uni polinom ( dati incepand cu gradul cel mai mic), calculati valoarea polinomului intr-un
punct Y.
5.2
L11. Cmmdc. Cmmmc
C.m.m.d.c. este acronimul (prima liter de la fiecare cuvnt) de la cel mai mare divizor comun i se aplic pentru dou numere
naturale.
Problema. Fie doua numere naturale A si B. Sa se determine cel mai mare divizor comun a lui A si B.
Sa citim iar. Practic trebuie sa determin un numar natural care sa fie divizor atat pentru A cat si pentru B. Daca sunt mai multe
numere in aceasta situatie, atunci il aleg pe cel mai mare. Ceea ce ma duce cu gandul la
Varianta 1.
citeste A, B;
cmmdc=0;
pentru D=1 pana la A executa
daca (A%D==0 si B%D==0 ) atunci cmmdc=D;
scrie cmmdc;
Practic, cmmdc-ul va fi cel mult unul dintre numere. As putea sa fiu prevazator si sa aleg ca limita superioara pe cel mai mic dintre
A si B. Si conditia de numitor comun se poate rescrie A%D +B%D==0.
Varianta 2.
citeste A,B
min=A; daca (min>B) atunci min=B;
pentru D=1 pana la min executa
daca (A%D +B%D==0) atunci cmmdc=D;
scrie cmmdc;
Varianta 3.
Problema nu e noua, Euclid (cca 325 265 .Hr.!!!!!) s-a gandit si el la acelasi lucru si a gasit o solutie.
OBS. M-am gandit de multe ori cum sa explic elevilor ce anume l-a facut pe Euclid sa se gandeasca la problema cmmdc si mi-am
imaginat urmatorul scenariu: Euclid avea o camera de latime A si lungime B pe care sotia lui vroia sa o acopere cu placi
patrate de gresie. Pentru a-si impresiona prietenele, placile trebuiau sa acopere integral suprafata camerei si sa fi cat mai
mari. Cum a rezolvat Euclid problema? Practic trebuie desenat un caroiaj cu patrate de latura CMMDC.
Daca D este divizorul comun a lui A si B, atunci estista A2 si B2 asa incat:
A=D*A2
B=D*B2 si deduce ca si diferenta acestor numere are acelasi divizor comun
A-B=D*(A2-B2)
Practic, in lenea lui de a calcula cmmdc(A,B), Euclid propune mereu o pereche mai mica (A-B, B) daca A>B sau (A, B-A) daca
B>A. Deci, cmmdc(A, B) este
Se observa ca in primele doua cazuri trebuie sa reluam algoritmul, ceea ce ne duce cu gandul la urmatoarea secventa:
citeste A,B
cat timp (A!=B) executa
daca (A>B) atunci A=A-B;
altfel B=B-A;
scrie A;
Varianta 4.
Deci varianta 3 e de acum 2000 de ani! Intre timp, s-a mai facut o varianta. Daca A=23456 si B=89 ar trebui sa se efectueze o
multime de scaderi a lui B din A. Scaderi repetate, pana nu se mai poate scadea pe B din A! Asta este o impartire si ce ramane in
A este restul. In consecinta, pe cel mai mare il vom transforma in restul impartirii. Cand ne oprim? Ne vom opri cand A sau B vor fi
nule, ceea ce inseamna ca cealalta valoare, nenula, va fi CMMDC.
citeste A,B;
cat timp (A*B!=0) executa //daca nici unul nu e nul.
daca (A>B) atunci A=A%B;
altfel B=B%A;
scrie A+B; //afisez valoarea nenula
Varianta 5.
Desi varianta 4 e o solutie respectabila, inca nu e de ajuns. Practic, la fiecare iteratie se executa 2 teste cel din CAT TIMP si cel
din DACA. Varianta urmatoare foloseste aceeasi idee de mai sus dar elimina unul din teste.
citeste A,B;
cat timp (B!=0) executa
{R=A%B; A=B; B=R;}
//se iese cand B este nul=>
scrie A;
Analiza variantelor
Evident, ultima varianta este cea mai buna. Am explicat deja ratiunile prin care s-a trecut de la o varianta la alta. In vederea
examenului de bacalaureat va trebuie toate variantele, indeosebi ultima pentru momentul cand va trebui sa programati.
Calculul CMMMC
Pentru calculul matematic a cmmdc pentru doua numere A si B, se realizeaza descompunerea in factori primi si apoi se considera
termenii comuni, la puterea cea mai mica.
Pentru calculul matematic a cmmmc pentru doua numere A si B, se realizeaza descompunerea in factori primi si apoi se considera
termenii comuni si necomuni, la puterea cea mai mare.
Practic daca as scrie produsul A*B ca inmultire intre descompunerile lor, as observa ca toti termenii existenti sunt fie parte a
CMMDC, fie parte a CMMMC.
De aici apare si relatia A*B=CMMDC(A,B)*CMMMC(A,B). Practic ne vom folosi de CMMMC(A,B)=A*B/CMMDC(A,B).
citeste A,B
A2=A; B2=B; //salvez separat datele initiale
//calculez CMMDC
cat timp (B!=0) {R=A%B; A=B; B=R;}
//afisez CMMMC
scrie CMMMC este , A2*B2/A.
6.
L6. Instructiunea PENTRU EXECUTA
Exista trei instructiuni (structuri) repetitive folosite in toate limbajele:
instructiunea repetitiva cu test initial CAT TIMP (WHILE) (se foloseste cand numarul de repetitii este nedefinit)
instructiunea repetitiva cu test final REPETA-PANA CAND/EXECUTA CAT TIMP (DO WHILE sau REPEAT) (se foloseste
cand numarul de repetitii este nedefinit)
instructiunea repetitiva cu un numar cunoscut de pasi PENTRU (FOR) (se foloseste cand numarul de repetitii
este cunoscut un numar fix de ori.)
Observatii:
practic, pentru fiecare valoare a lui i, intai se testeaza daca nu s-a depasit valoarea finala 10 si apoi se executa
instructiunea;
practic , secventa de mai sus me explica faptul ca instructiunea pentru este o clona a instructiunii cat timp.
instructiunea este ceruta daca descrierea algorimului spune de la valoarea X la valoarea Y, pentru primele X valori,
de X ori,
Exemplul 1.
Sa se afiseze numerele pare pana la o valaore N, naturala.
intreg n,i;
citeste n;
pentru i<- 0,n executa
daca (i%2==0) atunci scrie i.
Observatii:
algoritmul ia fiecare valoare intre 0 si n si o testeaza daca este para (restul impartirii lui i la 2 sa fie nul : i%2==0)
se efectueaza n pasi din care jumatate sunt gresiti; trebuie o varianta mai buna
Exemplul 2.
Aceeasi problema dar incercam sa mergem din doi in doi
o
intreg n,i; citeste n; pentru i<-0,n,2 executa scrie i.
o
intreg n,i; citeste n; pentru i<-0,n/2 executa scrie i*2.
Observatie:
in primul caz, 2-ul de dupa n (i<-0,n,2 ) stabileste cresterea lui i cu 2 si nu cu 1 asa cum este implicit
in al doilea caz, ne folosim de faltul ca valorile cautate sunt pare, divizibile cu 2;
Exemplul 3
Sa se calculeze suma primelor N numere naturale.
o
evident, stim formula n*(n+1)/2 dar sa incercam un algoritm;
o
va trebui sa adunam, la o suma , toate valoarile de la 1 la n
intreg n,i,suma;
citeste n;
suma<-0;
pentru i<- 0 ,n executa suma<- suma +i;
scrie suma.
Exemplul 3.
Se citeste un sir de N valori intregi. Sa se determine cea mai mare valoare citita (valoarea maxima dintr-un sir).
intreg n,i,max,val;
citeste n;
citeste max;
pentru i<-2,n executa {citeste val; daca val>max atunci max<-val;};
scrie val.
6.1
L9. Algoritmi fundamentali. iruri de numere
Pentru a prelucra un ir de numere trebuie s tim fie numrul de valori n discuie (ir cu numr cunoscut de valori), fie s avem o
valoare care s marcheze sfritul irului (de obicei zero).
natural x, n, i;
citeste N
pentru i=1,N executa
{
citeste X;
//prelucrez X
........
}
citeste x;
cat timp (x!=0) {
//prelucrez valorea X
.........
//trec la valoarea urmatoare
citeste X
}
Probleme
1.
2.
3.
4.
5.
Presupunand ca sirul reprezinta coeficientii uni polinom ( dati incepand cu gradul cel mai mic), calculati valoarea polinomului intr-un
punct Y.
6.2
L10. Algoritmi fundamentali. Divizibilitate. N este prim?
Divizibilitate
Problema. Pentru un N dat, care sunt divizorii lui N?
Multimea divizorilor lui N este cuprinsa intre valorile 1 si N. Un numar D este divizor al lui N daca N se imparte exact la D. Pentru
noi, impartirea exacta inseamna ca restul impartirii lui N la D este zero. Trebuie sa cautam acele valori intre 1 si N la care N se
imparte exact. Vom aifsa si vom numara aceste valori.
natural N, D, NR;
NR=0;
citeste N;
pentru D=1, N executa
daca (N%D==0) atunci { scrie D; NR=NR+1}
scrie NR;
Cu numarul de divizori putem stabili daca numarul N este prim.
Am redus doua teste : nu mai testam cazul D=1 si D=N. De asemenea, profitam de situatia in care gasim primul divizor pentru a
iesi din repetitie. Totusi, pentru cazul in care numarul ar fi prim, inca se executa N-2 pasi.
Varianta 2. Numarul 2 este cel mai mic potential divizor. Deduc ca numarul N/2 este cel mai mare potential divizor.
D=2;
cat timp (D<=N/2 si N%D!=0) executa D=D+1;
daca (N%D==0) atunci scrie divizibil
In aceasta varianta se executa, in cel mai rau caz, N/2 operatii. Super! Am redus munca la jumatate! Se poate mai bine?
Varianta 3. Sa cercetam, in continuare, perechile de potential divizori: 2 cu N/2, 3 cu N/3, 4 cu N/4, . Observ ca pe masura ce
primul termen creste, al doilea scade. Deduc ca, la un moment dat cei doi termeni pot fi egali. Adica ar putea fi un element X astfel
incat N==X*X sa fie adevarat! In consecinta X=radical(N) . Deci ultima pereche care ar trebui studiata este cea cu radical (N).
D=2;
cat timp (D<=radical(N) si N%D!=0) executa D=D+1;
daca (N%D==0) atunci scrie divizibil
altfel scrie prim
Este cert ca radical(N)<N/2. Iata ca am obtinut un numar mai mic de operatii. Sa cercetam cat de eficienti sunt algoritmii nostri.
Numarul N=611953 este prim, spun unii.
varianta 1 va executa maxim 611951 pasi
varianta 2 va executa maxim 305 976 pasi
E ceva, nu?
Varianta 4. Si inca mai merge
daca (N==2) atunci scrie prim
altfel daca (nN%2==0 ) atunci scrie divizibil
altfel {
o
D=3;
o
cat timp (D<=radical(N) si N%D!=0) executa D=D+2;
o
daca (N%D==0) atunci scrie divizibil
o
altfel scrie prim }
Algoritmul de mai sus verifica daca N este 2 si elimina din discutie numerele pare. Pentru ca majoritatea numerelor prime sunt
impare, parcurg numai valorile impare si le intreb daca nu cumva sunt divizori pentru N.
Varianta 4 va efectua maxim 390 pasi pentru N=611953.
7.
L7. Instruciunea EXECUT CT TIMP
Exista trei instructiuni (structuri) repetitive folosite in toate limbajele:
instructiunea repetitiva cu test initial CAT TIMP (WHILE) (se foloseste cand numarul de repetitii este nedefinit)
instructiunea repetitiva cu test final REPETA-PANA CAND/ EXECUTA CAT TIMP (DO WHILE sau REPEAT) (se foloseste
cand numarul de repetitii este nedefinit)
instructiunea repetitiva cu un numar cunoscut de pasi PENTRU (FOR) (se foloseste cand numarul de repetitii
este cunoscut)
se executa instructiunea
se stabileste valoarea de adevar a expresiei logice
daca valoarea conditiei este ADEVARAT atunci se revine la pasul 1
daca valoarea conditiei este FALSA atunci se continua cu instructiunea de dupa EXECUTA CAT TIMP
Observatii:
instructiunea EXECUTA CAT TIMP este o instructiune repetitiva conditionata posterior (sau cu test final)
intai executa instructiunea de repetat si apoi verifica necesitatea repetarii; instrutiunea se executa macar o data
Putewti folosi aceasta instructiune pentru algortimul de prelucrare a cifrelor unui numar natural N:
executa {cif<- n%10; prelucrez cifra ; n<-n/10} cat timp (n!=0);
Exemple:
sa se afiseze cifrele numarului
sa se numere cate cifre are N
sa se stabileasca de cate ori apare o cifra anume
sa se determine cifra maxima/minima din numar
sa se creeze oglinditul numarului N (N=1234 => 4321)
sa se stabileasca daca N estre palindrom (egal cu oglinditul sau). Ex: 12321, 11, 121,
7.1
L8. Algoritmi fundamentali. Prelucrarea cifrelor unui numr natural
Fie N un numar natural. Avem nevoie sa prelucram pe rand cifrele unui numar natural.
In prelucrarea cifrelor numarului, cel mai usor ajungem la ultima cifra (N%10) . Dupa prelucrarea ei, ultima cifra va trebui inlaturata
(N=N/10). Si totul trebuie repetat cat timp N mai are cifre (N!=0).
De vreme ca nu stim cate cifre are N, nu putem folosi intructiunea FOR/PENTRU. Raman instructiunile repetitive cu un numar
necunoscut de pasi : CAT TIMP EXECUTA/WHILE si EXECUTA CAT TIMP/ DO WHILE.
Pentru CAT TIMP EXECUTA/WHILE am un contraargmuent. Algoritmul ar trebui sa fie
8.
L7.2. Care instruciune repetitiv este mai bun?
Desi sunteti tentati sa alegeti trebuie sa stit ca ambele instructiuni au aceeasi capacitate. Toata problema este sa verificati in
algoritmul dumneavoastra daca trebuie sau nu efectuat un test inainte de executarea instructiunii/instructiunilor de repetat.
Simularea instructiunii CAT TIMP EXECUTA cu EXECUTA CAT TIMP. Instructiunea CAT TIMP EXECUTA intai testeaza si apoi
executa; daca comparam secventele de executie observam ca la CAT TIMP EXECUTA intai apare un test/conditie. si apoi este
identica cu EXECUTA CAT TIMP; nu ramane decat sa folosim o instructiune de test pentru aceasta conditie;
cat
timp (exp_logica) executa instructiune;
Observati ca pentru transformarea unei instructiuni cat timp in una executa cat timp, nu trebuie dacat sa
identificati conditia si secventa care se repeta; apoi copiati corespunzator in sablon.
Simularea instructiunii EXECUTA CAT TIMP cu CAT TIMP EXECUTA .
9.
L14. Conversia unui numr din baza 10 n baza B
Un numar NB scris in baza B are cifre cu valori intre 0 si B-1.
Pentru a obtine reprezentarea numarului N10 in baza B, trebuie sa realizam un sir de impartiri repetate la B.
Fie N10=2490 si B=8
2490 impartit la 8 produce catul 311 si restul 2.
311 impartit la 8 produce catul 38 si restul 7
38 impartit la 8 produce catul 4 si restul 6
citeste N10;
NB=0;
p10=1;
cat timp(N10!=0)
{
NB=NB+P10*(N10%B);
P10=P10*10;
N=N/B;
}
scrie NB.
10.
L13. Conversia unui numr din baza B n baza 10
Un numar NB scris in baza B are cifre cu valori intre 0 si B-1. Problema noastra este sa determinam ce numar N10 ii corespunde
lui NB pentru baza 10.
Pentru aceasta sa observam urmatorul exemplu. Un numar in baza 10, N10=2490 poate fi scris si in forma canonica, adica
N10=2*10^3+4*10^2+9*10^1+0*10^0.
Fie NB=4672 scris in baza B=8. Pentru a converti NB in baza 10 trebuie sa il scriem in forma canonica.
N10=4*8^3+6*8^2+7*8^1+2*8^0. Dupa calcule se obtine valoarea N10=2490.
Practic trebuie sa calculam o suma de produse a cifrelor din NB cu puteri ale bazei. Vom folosi algoritmul de prelucrare a cifrelor
unui numar (NB).
citeste NB, B;
N10=0;
PB=1;
executa{
N10=N10+(NB%10)*PB;
PB=PB*B;
NB=NB/10;
}cat timp (NB!=0);
scrie N10;
11.
L12. irul lui Fibonacci
irul lui Fibonacci este 1, 1, 2, 3, 5, 8, 13, 21, 34, . i are legtur cu celebrul numr de aur.
Se observ c irul ncepe cu valorile 1 i 1 , dup care, fiecare nou valoare se obine prin adunarea ultimelor dou valori:
F(1)=1
F(2)=1
F(n)=F(n-1)+F(n-2)
Limbajul C/C++
1. Alfabet, identificatori, constante , variabile
2. Tipuri
3. Operatori. Expresii
4. Structura unui program C/C++
5. Citirea. Afisarea
6. Atribuirea
7. Instructiunea IF
8. Instructiunea DO WHILE
9. Instructiunea WHILE
10. Instructiunea FOR
11. Algoritmi fundamentali
1.
2.
3.
4.
Cmmdc. Cmmmc
5.
6.
7.
12. Tablouri.
1.
Identificatori
Cu caracterele din alfabetul de mai sus se pot construi cuvinte. In programare aceste cuvinte se
numescidentificatori. Identificatorii sunt de doua tipuri:
identificatori proprii limbajului (cuvinte rezervate, din care sunt formate instructiunile): for, while, if, do,
identificatori ai programatorului: trebuie sa fie formati din litere, cifre si semnul _ ; regula este ca primul
caracter sa fie obligatoriu litera.
Identificatorii programatorului pot avea rolul:
Variabilele
O variabila este un identificator, purtator a unei singure valori. O variabila se caracterizeaza prin:
nume
tip de data (ceea ce determina spatiul de memorie alocat variabilei si in consecinta, domeniul de
valori care se pot memora in variabila respectiva)
locatie de memorie
Exista si aici cateva reguli:
2.
in principiu, la inceputul programului trebuie sa declarati ce variabile folositi si tipul fiecareia din ele
nu puteti folosi o variabila nedeclarata sau care inca nu a primit valoare (neinitializata);
o exceptie de la regula o reprezinta cazul valorilor intregi care se initializeaza automat cu zero (ordonat ar fi
sa cititi sau sa initializati voi fiecare variabila)
limbajul C/C++ face distinctie intre litere mari si mici
o
identificatorul FOR va genera eroare, pentru ca limbajul cunoaste doar for;
o
variabilele NR, nR, nr, Nr sunt diferite din punctul de vedere al C/C++
L4. Tipuri
Tipurile intregi
Tipurile intregi din C/C++ sunt: enum, short int, int, unsigned int, long, unsigned long.
Pentru fiecare variabila se aloca (rezerva) un spatiu de memorie conform cu tipul ei. Acest lucru influenteaza domeniul de valori
care se poate aloca variabilei:
o
o
o
o
o
o
o
o
Observatii:
valorile UNSIGNED (eng: fara semn) sunt valori naturale, cu valori pozitive
in sprijinul ideii de mai sus, ca tipul determina domeniul de valori, venim cu urmatoarea demonstratie:
o
presupunem ca avem o variabila A de tip int (pe 16 biti); aceasta inseamna ca valoarea maxima ce se poate
memora este un sir de 15 pozitii binare cu 1 (primul bit memoreaza semnul); daca convertim aceasta valoare din baza 2 in
baza 10 (puteti folosi aplicatia CALCULATOR din Windows) obtinem exact 32767
o
analog, pentru o variabila unsigned int (16 biti) putem memora 16 pozitii binare cu 1 (din cauza unsigned, nu mai
avem semn adica valori pozitive); sirul de 16 pozitii binare reprezinta valoarea 65535 din baza 10.
Tipurile reale
Tipul caracter
char -127 .. 127 (pentru fiecare caracter este asociata, in mod unic, o valoare de la 0 la 127; aceasta asociere se
numeste CODUL ASCII)
3.
o
o
Prioritatea operatorilor
4.
3.
4.
afisarea rezultatelor
int a,b,c;
int main()
{//citirea datelor initiale; initializarea altor variabile;
cin>>a>>b;
//prelucrarea datelor
c=a+b;
//afisarea datelor
cout <<"afisarea rezulattului"<<endl;
cout<<<<a<<'+'<<b<<'='<<a+b;
cout<<"Suma calculata
este "<<c;
return 1;}
Observatie
instructiunea return permite intreruperea brusca a executiei unui program; puteti folosi aceasta instructiune daca , din
diverse motive doriti intreruperea brusca a executiei unui program.
5.
Instructiunea CIN
Sintaxa: cin>>variabila1>>variabila2;
Efect: se preiau de la tastatura (Console INput) valori pentru fiecare variabila din sir;
Cerinte : folosirea instructiunii necesita #include <iostream.h>
Exemplu:
int A,B; cin>>A>>B;
Pe rand, se introduc valori de la tastatura pentru variabilele intregi A si B.
Instructiunea COUT
Sintaxa: cout<<expresie1<<expresie2;
Efect: se afiseaza, pe rand, valorile expresiilor;
Cerinte: necesita, de asemenea, folosirea #include <iostream.h>
Exemple:
cout<<Rezultatul este<<endl<< A<<+'<<B<<='<<A+B;
s-au afisat :
o
constanta sir de caractere (text) Rezultatul este
o
constantele caracter + si =
o
valorile variabilelor A si B
o
valoarea expresiei A+B
6.
L8. Atribuirea
Variabilele pot primi valori prin citire sau atribuire.
Atribuirea
Sintaxa: variabila=expresie;
Efect:
Exemple:
A=0;
B=5;
A=B+6;
A=B+A; (in A se va memora suma dintre A si B)
un caz deosebit este incrementarea (cresterea cu 1 a valorii unei variabile)
o
a=a+1;
o
aceasta operatie se mai scrie a++; (++ este operator unar)
cum va place!
Probleme
1.
Teodor is consuma jumatate din salariul sau pe facturi. Cititi salariul lui Teodor si afisati cu cat ramane Teodor.
2.
Cititi de la tastatura distanta si timpul necesar unui tren pentru a parcurge respectiva distanta. Calculati viteza medie de
deplasare.
3.
Ana si Bogdan sunt colegi de banca. In pauza s-au gandit sa-si schimbe scaunele intre ei astfel incat , in orice moment,
fiecare sa stea pe un scaun. Copiii astia chiar n-au treaba!!!
Observatii:
la problema 1 pot apare urmatoarele dificultati:
o
daca salariul are valoare impara, rezultatul nu este real => float rez=(float) salar/2;
o
salariul este declarat int salar; si introduceti un salariu mai mare de 32767 rezultatele sunt imposibile; de ce? =>
variabilele de tip int nu pot depasi 32767; de aceea, valorile mai mari sunt trunchiate
Sa privim inainte:
din exemplele de mai sus este limpede ca variabilele/datele de intrare trebuiesc verificate inainte de a fi prelucrate
de aceea, vom studia in continuare instructiunea IF
7.
L9. Instructiunea IF
Instructiunea IF
Sintaxa: if (exp_logica) instrDA; else instrNU;
Efect:
Exemplu:
if (a%2==0) cout>>valoarea este para; else cout<< valoarea este impara;
se verifica daca restul impartirii la 2 a variabilei A este zero
daca DA se executa cout>>valoarea este para;
daca NU se executa cout>>valoarea este impara;
Observatii:
in C/C++ instructiunile, pe langa efectul lor, returneaza o valoare adevarat (1 unu) daca se executa corect si fals (0
zero) daca executia a fost eronata;
secventa if (a=b) instr1; else instr2; va executa intotdeauna numai instr1 pentru ca atribuirea a=b se executa corect
a nu se confunda a=b (lui a i se atribuie valoarea lui b) cu a==b (care verifica daca cele doua valori sunt egale)
daca in loc pentru o valoare a conditiei testate algortimul impune executarea a mai mult de o instructiune, acestea se vor
incadra intre acolade: if (conditie) { instructiuni pe ramura DA} else {instructiuni pe ramura NU};
Probleme:
1.
Fie N un numar natural. Sa se afiseze textul PAR sau IMPAR, functie de valoarea lui N.
2.
Fie N un numar natural. Sa se afiseze textul POZITIV, NEGATIV sau ZERO dupa caz.
3.
Fie A si B capetele unui interval. Sa se stabileasca daca o valoare X apartine intervalului [A,B].
4.
Fie A si B doua valori intregi. Sa se afiseze A si B in ordine crescatoare.
5.
Fie A si B doua valori intregi. Sa se calculeze X, solutia ecuatiei A*X+B=0.
Observatii:
1.
Se verifica valoarea expresiei N%2==0
2.
Se compara N cu 0 si se afiseaza dupa caz.
3.
Daca A este mai mare decat B, valorile trebuie interschimbate.
4.
5.
Trebuie verificat daca A nu este zero, caz in care se afiseaza un mesaj si se iese fortat, cu RETURN.
8.
instructiunea repetitiva cu test initial CAT TIMP (WHILE) (se foloseste cand numarul de repetitii este nedefinit)
instructiunea repetitiva cu test final REPETA-PANA CAND (DO WHILE sau REPEAT) (se foloseste cand numarul de
repetitii este nedefinit)
instructiunea repetitiva cu un numar cunoscut de pasi PENTRU (FOR) (se foloseste cand numarul de repetitii
este cunoscut un numar fix de ori.)
Instructiunea DO WHILE
Sintaxa: do { instructiuni} while (conditie) ;
Efect:
1.
2.
3.
4.
Observatii:
do-while se mai numeste instructiune cu test final sau conditionata posterior
observati ca intai se executa secventa de instructiuni (macar o data) si apoi se testeaza
succesiunea de operatii este instructiune, test, instructiune, test, .. test, instructiune, test.
Exemplu:
O problema la care putem folosi DO-WHILE este prelucrarea cifrelor unui numar natural/intreg. Cifrele vor fi prelucrate pe rand, de
la sfarsitul numarului catre inceput, de fiecare data taind ultima cifra (deja prelucrata). Algoritmul se reia pana cand nu mai sunt
cifre in numar, adica valoarea N ajunge la valoarea zero.
Sesizati ca orice numar are o ultima cifra, motiv pentru care intai prelucrez si tai , si apoi verific daca mai sunt cifre de prelucrat.
cin>>n;
do { //prelucrarea ultimei cifre
..............;
// tai ultima cifra
n=n/10;
} while (n!=0);
Observatii: puteti determina intai ultima cifra (int uc=n%10; ) si apoi sa prelucrati variabila uc
Probleme. fie N un numar natural.
1.
Cate cifre are N?
2.
Care este suma cifrelor lui N?
3.
Care este cea mai mare cifra din numar? (valoarea maxima). Analog minima.
4.
Sa se determine prima cifra a numarului N.
5.
De cate ori apare o cifra data C, in numarul N?
6.
Sa se genereze oglinditul numarului N. (daca N=1987 atunci oglinditul va fi 7891)
7.
Folosind problema de mai sus, stabiliti daca numarul N este palindrom.
9.
instructiunea repetitiva cu test initial CAT TIMP (WHILE) (se foloseste cand numarul de repetitii este
nedefinit)
instructiunea repetitiva cu test final REPETA-PANA CAND (DO WHILE sau REPEAT) (se foloseste
cand numarul de repetitii este nedefinit)
instructiunea repetitiva cu un numar cunoscut de pasi PENTRU (FOR) (se foloseste cand numarul
de repetitii este cunoscut un numar fix de ori.)
Instructiunea WHILE
Sintaxa :
Efect
1.
2.
3.
Observatii:
in esenta, cat timp valoarea expresiei logice este adevarata, se executa instructiunea
daca valoarea expresiei logice este falsa de la inceput atunci instructiunea nu se mai executa
daca WHILE trebuie sa repete mai mult de o instructiune, acestea se vor incadra intre acolade;
instructiunea WHILE se mai numeste repetitiva cu test initial sau conditionata anterior,
pentru ca intai verifica valoarea conditiei si apoi executa secventa ce trebuie repetata
Problema exemplu. Fie A si B doua valori naturale. Sa se simuleza impartirea cu rest a lui A la B (prin
scaderi repetate) si sa se determine catul si restul impartirii.
#include <iostream.h>
void main()
{//declararea
int A, B, C=0;
//citirea
cin>>A>>B;
//prelucrarea
while(A>=B) {A=A-B; C++;};
//Afisarea rezultatelor
cout<<"catul este :"<<C<<endl;
cout<<"restul este : "<<A;
}
Explicatii. Cand impartim pe A la B cautam de cate ori se cuprinde B in A, altfel spus cate scaderi ale lui
B din a se pot face.
Un tip e problema ce necesita folosirea instructiunii WHILE este prelucrarea unui sir de valori ce se
incheie cu zero.
Ideea : Se citeste fiecare valoare si daca este nenula se prelucreaza; Acest pas se repeta pana citim valoarea
zero. (Ex: 23, -4, 5, 12, 79, 0).
Codul corespunzator este:
cin>>x;
While (x!=0) { //prelucrez valoarea X citita;
..............................
//citesc urmatoarea valoare din sir
cin>>x;};
10.
Instructiunea FOR
Exista trei instructiuni (structuri) repetitive folosite in toate limbajele:
instructiunea repetitiva cu test initial CAT TIMP (WHILE) (se foloseste cand numarul de repetitii este nedefinit)
instructiunea repetitiva cu test final REPETA-PANA CAND (DO WHILE sau REPEAT) (se foloseste cand numarul de
repetitii este nedefinit)
instructiunea repetitiva cu un numar cunoscut de pasi PENTRU (FOR) (se foloseste cand numarul de repetitii
este cunoscut un numar fix de ori.)
Sintaxa:
Efect:
pentru fiecare valoare a contorului i intre expresia initiala si expresia finala se executa instructiunea;
Observatii:
instructiunea este ceruta daca descrierea algorimului spune de la valoarea X la valoarea Y, pentru primele X valori,
de X ori,
11.1.
P10=P10*10;
N=N/B;
}
scrie NB.
11.2
11.3
F(1)=1
F(2)=1
F(n)=F(n-1)+F(n-2)
C=A+B;
//pregatim noua pereche
A=B;B=C}
scrie B;}
11.4
Varianta 1.
citeste A, B;
cmmdc=0;
pentru D=1 pana la A executa
daca (A%D==0 si B%D==0 ) atunci cmmdc=D;
scrie cmmdc;
Practic, cmmdc-ul va fi cel mult unul dintre numere. As putea sa fiu prevazator si sa aleg ca limita superioara pe cel mai mic dintre
A si B. Si conditia de numitor comun se poate rescrie A%D +B%D==0.
Varianta 2.
citeste A,B
min=A; daca (min>B) atunci min=B;
pentru D=1 pana la min executa
daca (A%D +B%D==0) atunci cmmdc=D;
scrie cmmdc;
Varianta 3.
Problema nu e noua, Euclid (cca 325 265 .Hr.!!!!!) s-a gandit si el la acelasi lucru si a gasit o solutie.
OBS. M-am gandit de multe ori cum sa explic elevilor ce anume l-a facut pe Euclid sa se gandeasca la problema cmmdc si mi-am
imaginat urmatorul scenariu: Euclid avea o camera de latime A si lungime B pe care sotia lui vroia sa o acopere cu placi
patrate de gresie. Pentru a-si impresiona prietenele, placile trebuiau sa acopere integral suprafata camerei si sa fi cat mai
mari. Cum a rezolvat Euclid problema? Practic trebuie desenat un caroiaj cu patrate de latura CMMDC.
Daca D este divizorul comun a lui A si B, atunci estista A2 si B2 asa incat:
A=D*A2
B=D*B2 si deduce ca si diferenta acestor numere are acelasi divizor comun
A-B=D*(A2-B2)
Practic, in lenea lui de a calcula cmmdc(A,B), Euclid propune mereu o pereche mai mica (A-B, B) daca A>B sau (A, B-A) daca
B>A. Deci, cmmdc(A, B) este
Se observa ca in primele doua cazuri trebuie sa reluam algoritmul, ceea ce ne duce cu gandul la urmatoarea secventa:
citeste A,B
cat timp (A!=B) executa
daca (A>B) atunci A=A-B;
altfel B=B-A;
scrie A;
Varianta 4.
Deci varianta 3 e de acum 2000 de ani! Intre timp, s-a mai facut o varianta. Daca A=23456 si B=89 ar trebui sa se efectueze o
multime de scaderi a lui B din A. Scaderi repetate, pana nu se mai poate scadea pe B din A! Asta este o impartire si ce ramane in
A este restul. In consecinta, pe cel mai mare il vom transforma in restul impartirii. Cand ne oprim? Ne vom opri cand A sau B vor fi
nule, ceea ce inseamna ca cealalta valoare, nenula, va fi CMMDC.
citeste A,B;
cat timp (A*B!=0) executa //daca nici unul nu e nul.
daca (A>B) atunci A=A%B;
altfel B=B%A;
scrie A+B; //afisez valoarea nenula
Varianta 5.
Desi varianta 4 e o solutie respectabila, inca nu e de ajuns. Practic, la fiecare iteratie se executa 2 teste cel din CAT TIMP si cel
din DACA. Varianta urmatoare foloseste aceeasi idee de mai sus dar elimina unul din teste.
citeste A,B;
cat timp (B!=0) executa
{R=A%B; A=B; B=R;}
//se iese cand B este nul=>
scrie A;
Analiza variantelor
Evident, ultima varianta este cea mai buna. Am explicat deja ratiunile prin care s-a trecut de la o varianta la alta. In vederea
examenului de bacalaureat va trebuie toate variantele, indeosebi ultima pentru momentul cand va trebui sa programati.
Calculul CMMMC
Pentru calculul matematic a cmmdc pentru doua numere A si B, se realizeaza descompunerea in factori primi si apoi se considera
termenii comuni, la puterea cea mai mica.
Pentru calculul matematic a cmmmc pentru doua numere A si B, se realizeaza descompunerea in factori primi si apoi se considera
termenii comuni si necomuni, la puterea cea mai mare.
Practic daca as scrie produsul A*B ca inmultire intre descompunerile lor, as observa ca toti termenii existenti sunt fie parte a
CMMDC, fie parte a CMMMC. De aici apare si relatia A*B=CMMDC(A,B)*CMMMC(A,B). Practic ne vom folosi
de CMMMC(A,B)=A*B/CMMDC(A,B).
citeste A,B
A2=A; B2=B; //salvez separat datele initiale
//calculez CMMDC
cat timp (B!=0) {R=A%B; A=B; B=R;}
//afisez CMMMC
scrie CMMMC este , A2*B2/A.
11.5
natural N, D, NR;
NR=0;
citeste N;
pentru D=1, N executa
daca (N%D==0) atunci { scrie D; NR=NR+1}
scrie NR;
Cu numarul de divizori putem stabili daca numarul N este prim.
Am redus doua teste : nu mai testam cazul D=1 si D=N. De asemenea, profitam de situatia in care gasim primul divizor pentru a
iesi din repetitie. Totusi, pentru cazul in care numarul ar fi prim, inca se executa N-2 pasi.
Varianta 2. Numarul 2 este cel mai mic potential divizor. Deduc ca numarul N/2 este cel mai mare potential divizor.
D=2;
cat timp (D<=N/2 si N%D!=0) executa D=D+1;
daca (N%D==0) atunci scrie divizibil
altfel scrie prim
In aceasta varianta se executa, in cel mai rau caz, N/2 operatii. Super! Am redus munca la jumatate! Se poate mai bine?
Varianta 3. Sa cercetam, in continuare, perechile de potential divizori: 2 cu N/2, 3 cu N/3, 4 cu N/4, . Observ ca pe masura ce
primul termen creste, al doilea scade. Deduc ca, la un moment dat cei doi termeni pot fi egali. Adica ar putea fi un element X astfel
incat N==X*X sa fie adevarat! In consecinta X=radical(N) . Deci ultima pereche care ar trebui studiata este cea cu radical (N).
D=2;
cat timp (D<=radical(N) si N%D!=0) executa D=D+1;
daca (N%D==0) atunci scrie divizibil
altfel scrie prim
Este cert ca radical(N)<N/2. Iata ca am obtinut un numar mai mic de operatii. Sa cercetam cat de eficienti sunt algoritmii nostri.
Numarul N=611953 este prim, spun unii.
varianta 1 va executa maxim 611951 pasi
E ceva, nu?
Varianta 4. Si inca mai merge
daca (N==2) atunci scrie prim
altfel daca (nN%2==0 ) atunci scrie divizibil
altfel {
o
D=3;
o
cat timp (D<=radical(N) si N%D!=0) executa D=D+2;
o
daca (N%D==0) atunci scrie divizibil
o
altfel scrie prim }
Algoritmul de mai sus verifica daca N este 2 si elimina din discutie numerele pare. Pentru ca majoritatea numerelor prime sunt
impare, parcurg numai valorile impare si le intreb daca nu cumva sunt divizori pentru N.
Varianta 4 va efectua maxim 390 pasi pentru N=611953.
11.6
natural x, n, i;
citeste N
pentru i=1,N executa
{
citeste X;
//prelucrez X
........
}
citeste x;
cat timp (x!=0) {
//prelucrez valorea X
.........
Probleme
1.
2.
3.
4.
5.
11.7