Numerele prime sunt acelea care sunt divizibile prin 1 și prin ele însele. A genera N numere prime înseamnă:
- se inițializează o variabilă K=1;
- a genera un număr impar A=2*L+1;
- a extrage radicalul din numerul impar A, obținând numărul B;
- dacă la extragerea radicalului partea zecimală este nulă, A nu este număr prim.
- a împărți numărul B la toate numele de la 2 la B-1;
- dacă una dintre împărțiri nu are rest înseamnă că numărul A nu este prim;
- dacă toate împărțirile sunt cu rest, X(K)=A și K=K+1;
- se majorează numărul A, A=A+2;
- procedeul se reia de la extragerea de radical atât timp cât K este mai mic decât N.
Subprogramul GNPRIM(...) generează un șir de N, numere prime cu N mai mare decât 5 și mai mic decât 1001.
SUBROUTINE GNPRIM(N,X,IK)
DIMENSION X(1000) /1,2,3,5,7/
IK=0
IF((N.LT.5).OR.(N.GT.100)) GO TO 30
K=6
A=11.
10 CONTINUE
B=SQRT(A)
IVAL=INT(B)
AVAL=IVAL
IF((IVAL-B).EQ.0) GO TO 30
DO 20 I=2,IVAL-1
AI=I
IF(AMOD(AVAL,AI).EQ.0) GO TO 30
20 CONTINUE
X(K)=A
K=K+1
30 CONTINUE
A=A+1
IF(K.LT.N) GO TO 10
40 CONTINUE
IK=1
RETURN
END
Observăm că apar multe instrucțiuni GO TO datorită faptului că nu există implementare pentru structura DO-UNTIL
(07 ianuare 2018)
Showing posts with label FORTRAN IV. Show all posts
Showing posts with label FORTRAN IV. Show all posts
Sunday, January 7, 2018
Saturday, January 6, 2018
Programatorul de înaltă clasă
Și atunci, ca și acum, există o mare diversitate de programatori, dar cel mai bun lucru este să reușim să identificăm exact pe programatorul de care avem nevoie să ne rezolve în condițiile cele mai bune problema pe care vrem s-o rulăm pe calculator.
În acele vremuri nu oricine dorea chiar devenea programator pentru că:
- lipsea Internetul ca sursă de documentare;
- un calculator presupunea cunoștințe tehnice numeroase;
- limbajele de programare erau extrem de restrictive;
- centrele de calcul aveau criterii de angajare stricte;
- cărțile de programare nu erau laândemâna oricui;
- se formase deja o castă închisă a programatorilor;
- depanarea programelor era piatra dură de încercare.
Îți dădeai seama de programatorii foarte buni după cum le arătau fie imprimantele cu programe, fie foile de programare, căci un programator foarte bun scria un program, de asemenea, foarte bun, cu părți foarte clar structurate, cu includerea de secvențe elaborate și cu folosirea de chestiuni speciale care arătau că el știe meserie. Programatorul foarte bun realiza acel echilibru absolut necesar între cantitate și calitate și se vedea de la o poștă că programul său este precedat de nenumărate calcule din care a rezultat că secvențele incluse sunt dintre cele mai bune.
Și azi este tot așa. Mie nu trebuie să-mi arate cineva mii de programe scrise de el, ci un program. Acum când se lucrează online, oricare dintre programatori trebuie să se prezinte printr-o aplicație și după cum arată interfața, cât de șmecheră este aceasta și mai ales, dacă nu te lasă cu ochii-n soare, înseamnă că am în față un programator bun. Dacă programul se termină subit, aiurea cu un mesaj al sistemului de operare taman când eu vreau să mai rezolv și o altă problemă, înseamnă că respectiva hardughie este făcută după ureche și nu s-a ținut seama de cerințele unei aplicații online.
În vremurile de demult, programatorii de înaltă clasă aveau programe care:
- erau incluse în biblioteci renumite;
- rezolvau clase de probleme;
- admiteau probleme de dimensiuni nelimitate;
- gestionau numărul de iterații și precizia;
- aveau nenumărate validări care să asigure rezultate corecte și complete;
- erau înzestrate cu facilități de customizare;
- stocau seturi de date de intrare pe care le actualizau.
Am avut posibilitatea să cunosc pe unii dintre autorii acestor programe și să lucrez cu acele programe, pentru că la disciplina Programe aplicative care era predată studenților de la Facultatea de Cibernetică erau folosite astfel de produse program, multe dintre ele fiind făcute de firme străine, dar câteva precum VERONICA, CROCODIL, EMI, produsul de alocare și nivelare a resurselor, erau reaslizate de programatori din Centrul de Calcul al ASE. Duță Doru Lucian, Csaba Fabia, Ciobanu Gheorghe și Ruxanda Gheorghe sunt numai câțiva din marii programatori cu ale căror produse program am avut onoarea să lucrez la seminarii cu studenții ciberneticieni de-a lungul vremii. Despre Catona Ioan și Popescu Cristian voi scrie separat că ei au realizat implementarea la Danubiana a unor componente esențiale de calcul de necesar și de planificare a producției din sistemul BOMP al IBM. Erau și alți programatori eficienți care elaborau programe de bună calitate, căci nimeni nu rezista în branșă fără să aibă un nivel ridicat de performanță.
În programare ori ești bun și oferi beneficiarului programe care să-i rezolve problemele, ori nu ești bun și tot timpul spui că ești cu programul ba în compilare, ba în editare de legături, ba în testare, până beneficiarul se plictisește și caută pe altul care să-i rezolve problema.
La un moment dat am ajuns să identific programatorii de înaltă clasă și pe cei pe cale de a deveni programatori foarte buni prin câteva semne pe care le-am considerat esențiale, precum:
- modestia;
- tăcerea;
- munca;
- ordinea;
- perseverența;
- concentrarea;
- disciplina.
Imediat ce o persoană îmi înșirea ceea ce știe el să facă și lista era mult prea bogată, o includeam în grupul celor care zic că se pricep la multe, dar de fapt nu știu să facă prea multe. Imediat ce vedeam niște for de programare cu ștersături și împrăștiate, se clarificau multe dintre minusurile celui care se credea a fi bun programator. Imediat de programtorul vorbea despre bogata sa e.xperiență dar nu avea cel puțin un program pe care să-l văd la treabă, îmi dădeam seama că respectivul doar se laudă. Imediat ce într-o discuție apăreau schimbări prea dese de variante de soluții, îmi dădeau seama că respectivul nu prea are capacitatea de a porni ceva și de a soluționa, căci el intervine și tot timpul modifică, fără să finalizeze vreun program.
În programare este esențială identificarea programatorilor de înaltă clasă căci lor trebuie să li se dea să facă programe mari și grele pe care ei au capacitatea de a le duce la bun sfârșit. Este deja o tragedie când se acordă un cec în alb unui programator lăudăros, fără rezultate, dându-i-se să facă un program greu, căci respectivul nu-l va face, va încurca lucrurile. Dacă ceea ce respectivul a făcut este dat unui programator foarte bun să continue, cu siguranță că programatorul foarte bun va arunca la coșul de gunoi acel program fără valoare și va lua el de la zero realizarea programului. Eroarea de management are riscuri mari în ceea ce privește depășirea de termene de predare a lucrărilor.
(06 ianuarie 2018)
Calculul entropiei
Formula uzuală an entropiei H unui sistem care se făsește în una din stările S1, S2, S3, ..., Sn este:
unde:
n - numărul de stări ale sistemului
pi - probabilitatea ca sistemul să se afle în starea Si.
Trebuie reținut faptul că biblioteca de funcții a limbajului FORTRAN IV nu conține funcție care să permită extragerea logaritmului din baza 2, ceea ce impune lucrul cu subprogramul de calcul a logaritmului din baza 10. Deci se volosește formul:
log2(A) = log10(A)/log10(2.) Se va folosi funcția ALOG10().
Subprogramul ENTRO ( ...) care calculează entropia este:
SUBROUTINE ENTRO(P,N,H,IK)
IK=0
SUM=0.
DO 10 I=1,N
IF(((P(I).LT.0).OR.(P(I).GT.1.)) GO TO 30
SUM=SUM+P(I)
10 CONTINUE
IK=2
IF(SUM.NE.1) GO TO 20
IK=1
ALFA=1./ALOG10(2.)
H=0.
DO 20 I=1,N
H=H+P(I)*ALOG10(P(I))*ALFA
20 CONTINUE
H=-H
30 CONTINUE
RETURN
END
Subprogramul returnează IK=0 dacă datele nu sunt corecte, returnează IK=1 dacă rezultatul este cel dorit, returnează IK=2 dacă suma probabilităților nu este 1.
(06 ianuarie 2018)
Friday, January 5, 2018
Transpusa matricei rare
Matricea rară este reprezentată prin 3 vectori ce conțin informații doar despre elementele sale nenule. A calcula transpusa unei matrice rare înseamnă a interschimba conținutul vectorilor pentru linii cu cel pentru coloane. Subprogramul este:
SUBROUTINE TRARAR(LIN,ICOL,K, IK)
INTEGER AUX
IK=0
IF((K.LE.0).OR.(K.GT.N)) GO TO 20
K1=0
DO 10 I=1,K
AUX=ICOL(I)
ICOL(I)=LIN(I)
LIN(I)= AUX
LIN1(K1)=LIN(I)
ICOL(K1)=ICOL(I)
VAL1(K1)=VAL1(I)
10 CONTINUE
IK=1
20 CONTINUE
RETURN
END
Variabila AUX de tip întreg ajută la efectuarea interschimbului. Aici nu este necesar apelul subprogramului de efectuare a interschimbului elementelor unui vector pentru că s-ar efectua un apel inutil de subprogram, ori așa, am încorporat secvența pur și simplu că nu este lungă și este simplă.
(05 ianuarie 2018)
Matricele rare
Și în vremurile de demult se lucra cu probleme de mari dimensiuni, concretizate prin matrice cu grad de umplere redus, adică, matrice rare. Gradul de umplere al matricei A, G(A), este dat de formula:
G(A) = (K * 100) / (M*N)
unde:
K - numărul elementelor nenule din matricea A;
M - numărul de linii ale matricei A;
N - numărul de coloane ale matricei A.
O matrice A se zice că este rară dacă și numai dacă G(A) < 0,33%. Și în vremurile de demult lucrul cu matrice rare presupunea existența unei biblioteci de subprograme ce conținea subprograme privind:
- inițializarea matricei rare cu date provenind din cartele perforate;
- transformarea matricei definite full în matrice rară;
NORAR() - normalizarea de matrice rare;
- adunarea cu normalizare de matrice rare;
- scăderea cu normalizare de matrice rare;
- înmulțirea cu normalizare de matrice rare;
- inversarea cu normalizare a matricei rare;
- calcului transpusei unei matrice rare;
- comoararea de matrice rare.
Algoritmii care se implementau în acele vremuri țineau seama dacă se lucra sau nu cu matrice rare pentru că disponibilul de memorie internă era o mare problemă atunci. Se făceau calcule la sânge cum s-ar zice cu operanzii ca să se obțină rezolvări de probleme cu dimensiuni cât mai mari.
O matrice rară se memorează folosind 3 vectori, fiecare având câte NM componente și anume:
LIN(NM) - memorează liniile elementelor nenule;
ICOL(NM) - memorează coloanele elementelor nenule;
VAL(NM) - memorează valorile nenule din matricea A.
Se consideră că acest mod de memorare a unei matrice rare este eficient pentru o matrice A de tip double cu M linii și N coloane dacă și numai dacă 8 * M * N < 4 * 2 * K + 8 * K, unde K este numărul elementelor nenule din matricea A. Vectorii LIN() și ICOL() sunt definiți de tip INTEGER și fiecare componentă a lor are 4 bytes, iar vectorul VAL() are componente de câte 8 bytes fiecare pentru faptul că matricea A este definită ca având tipul DOUBLE.
(05 ianuarie 2018)
Thursday, January 4, 2018
Verificarea matricelor pozitiv definite
O matrice este pozitiv definită dacă toate elementele sale sunt mai mari strict decât zero. Subprogramul care verifică dacă matricea A cu M linii și N coloane este pozitiv definită este:
SUBROUTINE POZIT (A,N,N, IK)
IK=0
DO 10 I=1,M
IK=0
DO 10 I=1,M
DO 10 J=1,N
IF(A(I,J).LE.0) GO TO 20
10 CONTINUE
10 CONTINUE
IK=1
20 CONTINUE
RETURN
END
END
Variabila IK are valoarea zero dacă matricea nu este simetrică și are valoarea 1 dacă matricea este simetrică.
(04 ianuarie 2018)
Friday, December 29, 2017
Coeficienții ecuației de regresie simplă
Modelul de regresie simplă
pentru calculul coeficienților a și b se folosesc formulele
subprogramele de calcul pentru coeficienții a și b sunt următoarele:
SUMVEC - sumă elemente ale unui vector S=X(1)+X(2)+....+X(N);
PATRAT - ridicare la pătrat a elementelor unui vector Z(I)=X(I)*X(I);
PRODEL - calcul produse elemente ale unui vector Z(I)=X(I)*Y(I);
COEF - calculează coeficineții A și B după formulele de mai sus.
SUBROUTINE SUMVEC(X,N,S)
S=0.
DO 10 I=1,N
S=S+X(I)
10 CONTINUE
RETURN
END
SUBROUTINE PATRAT(X,N,S2)
S2=0.
DO 10 I=1,N
S2=S2+X(I)*X(I)
10 CONTINUE
RETURN
END
SUBROUTINE PRODEL(X,Y,Z,N)
DO 10 I=1,N
Z(I)=X(I)*Y(I)
10 CONTINUE
RETURN
END
SUBROUTINE COEF(X,Y,N,A,B,IK)
IK=0
IF(N.LE.0) GO TO 10
AN=N
IK=1
CALL PRODEL(X,Y,XY,N)
CALL SUMVEC(X,N,SX)
CALL SUMVEC(XY,N,SXY)
CALL SUMVEC(Y,N,SY)
CALL PATRAT(X,XN,SXX)
A=(AN*SXY-SX*SY)/(AN*SXX-SX*SX)
B=(SY-A*SX)/AN
10 CONTINUE
RETURN
END
Variabila IK este 0 dacă nu se calculează coeficienții că seriile de date sunt vide și IK=1 dacă acești coeficienți se calculează. Subprogramul COEF() se optimizează și dacă se elimină puzderia de apeluri de subprograme, dar devine mai mărișor și cu instrucțiuni ceva mai regrupate după cum urmează:
SUBROUTINE COEF(X,Y,N,A,B,IK)
IK=0
IF(N.LE.0) GO TO 20
AN=N
IK=1
SX=0.
SY=0.
SXX=0.
SXY=0.
DO 10 I=1,N
SX=SX+X(I)
SY=SY+Y(I)
SXX=SXX+X(I)*X(I)
SXY=SXY+X(I)*Y(I)
10 CONTINUE
A=(AN*SXY-SX*SY)/(AN*SXX-SX*SX)
B=(SY-A*SX)/AN
20 CONTINUE
RETURN
END
Dacă subprogramul ar fi scris în limbajul C++ cu siguranță că inițializările s-ar fi scris SX=SY=SXX=SXY=0.; ceea ce ar fi fost cu mult mai drăguț. Coeficienții ecuației de regresie simplă se calculează fie apelând tot felul de alte subprograme simple, fie scriind un subprogram ce include toate calculele. Trebuie ales un echilibru între a apela subprograme și a avea redundanță în program prin nereutilizare de componente de bibliotecă. Programatorul e suveran în programul pe care-l scrie și el alege dacă vrea să fie genial sau penibil, riscuș fiind în ambele cazuri 50% și 50%.
(29 decembrie 2017)
Thursday, December 28, 2017
Alegerea identificatorilor
În limbajul FORTRAN IV căci cu el se scriau programe până în 1977 numele de variabile care se construiau trebuiau să respecte următoarele reguuli:
- lungimea numelui de variabilă era maxim de 6 caractere;
- caracterele utilizate sunt literele mari A-Z, cifrele 0-9 și semnul $;
- primul caracter al numelui de variabilă este obligatoriu o literă.
Astfel, construcțiile:
VALOARE
COST
PROFIT
CERC
G981
$VAR
SUMA3
sunt nume de variabile corecte.
Construcțiile:
1RAZA nu este corectă că are prim caracter altceva decât o literă;
RAZA+ nu este corectă că are simbolul + care nu este nici literă și nici cifră;
PR_PL nu este corectă pentru că are în interior caracterul underscore cod HTML _;
A1234567B nu este corectă pentru că are mai mult de 6 caractere în componență.
Chiar dacă erau restricții așa de severe, programatorii de talent știau să aleagă astfel de denumiri ale variabilelor astfel încât să asigure un nivel de ortogonalitate pentru a nu le confunda unele cu altele. Se făceau o serie de convenții precum:
- variabila I era folosită pentru traversarea elementelor unui șir sau a liniilor matricei;
- variabila J era folosită pentru traversarea elementelor de pe coloanele unei matrice;
- variabila TEMP era folosită pentru rezultate temporare, ca și variabila AUX;
- variabilele M și N erau utilizate pentru a stabili număr de elemente sau de linii sau coloane;
- variabila XMED era folosită pentru media aritmetică;
- variabila DISP era folosită pentru dispersie;
- postfixul SORT era folosit pentru a marca faptul că rezultatul este sortat XSORT, YSORT;
- prefixul STOC era folosit pentru stocuri STOCPL, STOCRE, STOCEF;
- postfixul PL era utilizat pentru planificat, RE pentru realizat și EF pentru efectiv.
Fiecare programator își construia propriile reguli de a defini nume de variabile, dar ideia era ca programul să fie cât mai lizibil și el ca programator să nu depună eforturi inutile nici la depanare și nici la mentenanță, ci să meargă la sigur, având reguli pe care și le-a definit și le-a și respectat.
Programatorii care au lucrat foarte ermtic, definind nume de variabile după niște reguli foarte codificate au avut mari probleme în a depana programele, căci este foarte dificil să se umble într-o secvență care pleacă de la o relație matematică de forma:
să fie recunoscută cu lejeritate în construcția:
S234=S65*S987*S987
în loc de a scrie:
SCERC=PI*R*R
Este rezonabil mai ales când se construiesc subprograme să se utilizeze modalități omogene de definire a numelor de variabile EPS pentru acel epsilon care controlează precizia, ITER pentru numărul de iterații și pentru variabila de stare IK sau ISTARE sau pentru codul de eroare IERR și toți programatorii vor folosi fără retitență bibliotecile de subprograme, altfel le vor evita că sunt greoaie. Alegerea identificatorilor intră în arta programatorilor și adevărații programatori au și reguli de a construi nume de variabile care săă facă programele livibile și ușor de manevrat, fără ca expresiile să fie groaznic de sofusticate. În FORTRAN IV nu există cuvinte cheie și programatorii ar avea la dispoziție să folosească DO, IF, READ, GO TO RETURN ca nume de variabile. M-am jucat și eu cândva cu acestă facilitate și noroc că a fost doar o joacă pentru că un program cu astfel de variabile este o calamitate la depanare, căci există riscul de a distruge din prea mult zel chiar instrucțiuni corect scrise.
(28 decembrie 2017)
Activarea și dezactivarea de termeni
În informatică nu este rezonabil să fie șterse nivi articole din fișiere și nici termeni ai seriilor de date. Ceea ce ar trebui șters, trebuie dezactivat. În acest sens se asociază fiecărui element din șir un alt element care are valoarea 0 dacă este considerat neactiv sau șters din punct de vedere logic și nu fizic. La fișiere în articol se definește un câmp de un byte care este 0 dacă articolul este neactiv sau șters logic și 1 dacă este activ. Prin testarea acelui câmp, dacă are valoarea 1 se for face prelucrări, iar sacă este zero nu va fi utilizat nici articolul și nici elementul din șir.
Subprogramul care însumează elementele active ale șirului X de N componente va avea un subprogram care mai primește ca parametru un vector LL tot de N componente și LL(I) =0 ceea ce înseamnă că elementul nu este activ, este șters logic și nu intră în calcule, iar dacă LL(I)=1 elementul X(I) este activ și se folosește în prelucrări.
SUBROUTINE SUMVEC (X,LL,N,SUM)
SUM=0.
DO 10 I=1,N
IF(LL(I).EQ.0) GO TO 10
SUM=SUM+X(I)
10 CONTINUE
RETURN
END
Activând și dezactivând termeni se construiesc tot felul de eșantioane și se verifică tot felul de ipoteze. Prin operații simple se procedează la reconstituirea de toturi de date fără a fi nevoie să se refacă nici seriile de date și nici fișiere. Acum în prelucrările moderne se lucrează în mod curent cu vectori sau câmpuri de stare fără a mai se proceda șa ștergeri de elemente sau la ștergeri de articole.
(28 decembrie 2017)
Calcul medie mobilă
Media mobilă este un indicator statistic utilizat în studierea tendinței pe care o manifestă un fenomen în evoluția sa în timp. Fiind dat un șir X1, x2, x3, ..., xn-1, xn, a calcula media mobilă de ordin doi înseamnă a evalua expresii de forma xmi=(xi+xi+1)/2 cu i=1,2,3,...,n-1. A calcula media mobilă de ordin trei înseamnă a evalua expresii de forma xmi=(xi-1+xi+xi+1)/3 cu i=2,3,4,...,n-1.
Subprogramul care calculează media măbilă de ordin doi este:
SUBROUTINE MMOB2(X,N,XM,NN)
DO 10 I=1,N-1
XM(I)=(X(I)+X(I+1))/2.
10 CONTINUE
NN=N-1
RETURN
END
Subprogramul care calculează media măbilă de ordin treieste:
SUBROUTINE MMOB3(X,N,XM,NN)
DO 10 I=2,N-1
XM(I)=(X(I-1)+X(I)+X(I+1))/3.
10 CONTINUE
NN=N-2
RETURN
END
Există posibilitatea de a calcula mediile aritmetice în cascadă, adică medie aritmetică de ordin doi din termenii mediei aritmetice de ordin doi, ca în secvența:
........................
CALL MMOB2(X,N,XM,NN)
CALL MMOB2(XM,NN,XMM,NNN)
........................
XMM=((X(I)+2*X(I+1)+X(I+2))/4. și trendul evoluției unei serii dinamice se vede și mai bine.
(28 decembrie 2017)
Wednesday, December 27, 2017
Inversa matricei nesingulare
Inversarea matricei nesingulare este subprogramul cel mai căutat căci nenumărate aplicații folosesc inversa matricei, de la ecuația de regresie până la rezolvarea de sisteme liniare.
Am tot căutat subprograme pentru inversarea unei matrice și dintre toate am găsit unul interesant în cartea PROBLEME DE ANALIZĂ NUMERICĂ REZOLVATE CU CALCULATORUL avându-i ca autori pe acad. Gheorghe MARINESCU, Irona RIZZOLI, Ileana POPESCU și Cristina ȘTEFAN, carte publicată îmn Editura Academiei RSR, în anul 1987 și care la paginile 171-173 prezintă metoda iterativă HOTELLING-BODEWING de inversare a unei matrice. Se construiește șirul lui NEWTON de torma X(n+1) = X(n) +(I-X(n)*A)*X(n), unde A, I, X, sunt matrice pătrate cu m linii și m coloane, iar cifrele cuprinse între paranteze acolo la indici arată numărul iterației. X(n+1) înseamnă matricea X la iterația n+1, iar X(n) înseamnă matricea X la iterația n. I este matricea unitate, A este matricea ce trebuie inversată. Subprogramul are ca prim pas evaluarea expresiei X1=X0 +(I+X0*A)*X0. În final matricea X1 va conține matricea inversă, iar X0 este matricea de start care se obține prin convenție dintr-o evaluare de forma: X0 = 1./(maxaij) * I. Variabila maxaij este de fapt elementul maxim dintre elementele matricei A. În subprogramul INVMAT, X0 se va referi la matricea de la iterația precedentă și X1 se va referi la matyricea de la iterația următoare.
Se observă că aici trebuie să fie apelate alte subprograme precum:
- subprogram de copiere matrice;
- subprogram de adunare matrice;
- subprogram de scădere matrice;
- subprogram de calcul normă matrice;
- subprogram de înmulțire matrice.
Față de programul dat în cartea pe care am citat-o am făcut o serie de modificări, căci m-am gândit ca utilizatorul să fie scutit în a da el acolo valoarea de start X0, eroarea, criteriu de stopare a procesului iterativ și matricea unitate.
SUBROUTINE START(A,N,X0)
MAXAIJ=A(1,1)
DO 10 I=1,N
DO 10 J=1,N
IF(MAXAIJ.GT.A(I,J)) GO TO 10
MAXAIJ=A(I,J)
10 CONTINUE
DO 20 I=1,N
DO 20 J=1,N
20 X0(I,J)=0.
ALFA=1./MAXAIJ
DO 30 I=1,N
30 X0(I,I)=ALFA
RETURN
END
Această subrutină construiește matricea de start X0 ca fiind matricea unitate înmulțită cu inversul elementului maxim din matricea A.
Pentru scăderea a două matrice pătrate având n linii și n coloane se foolosește subprogramul:
SUBROUTINE ADMAT(A,B,C,N)
MAXAIJ=A(1,1)
DO 10 I=1,N
DO 10 J=1,N
C(I,J)=A(I,J)+B(I,J)
10 CONTINUE
RETURN
END
Pentru scăderea a două matrice pătrate având n linii și n coloane se foolosește subprogramul:
SUBROUTINE ADMAT(A,B,C,N)
MAXAIJ=A(1,1)
DO 10 I=1,N
DO 10 J=1,N
C(I,J)=A(I,J)-B(I,J)
10 CONTINUE
RETURN
END
Pentru copierea matricei A în matricea C, ambele având n linii și n coloane se foolosește subprogramul:
SUBROUTINE SCMAT(A,C,N)
MAXAIJ=A(1,1)
DO 10 I=1,N
DO 10 J=1,N
C(I,J)=A(I,J)
10 CONTINUE
RETURN
END
Generarea unei matrice unitate de ordin n se face cu subprogramul:
SUBROUTINE UNIMT(N,UNIT)
DO 20 I=1,N
DO 10 J=1,N
UNIT(I,J)=0.
10 CONTINUE
UNIT(I,I)=1.
20 CONTINUE
RETURN
END
Norma ANOR a matricei A este calculată cu subprogramul:
SUBROUTINE NMMAT(A,N,ANOR)
ANOR=ABS(A1,1))
DO 20 I=1,N
DO 10 J=1,N
IF(ANOR.GT.ABS(A(I,J)) GO TO 10
ANOR=ABS(A(I,J))
10 CONTINUE
RETURN
END
Pentru înmulțirea a două matrice A și B pătrate având n linii și n coloane, rezultatul fiind matricea C tot cu n linii și n coloane se foolosește subprogramul:
SUBROUTINE PRMAT(A,C,N)
MAXAIJ=A(1,1)
DO 20 I=1,N
DO 20 J=1,N
CIJ=0.
DO 10 K=1,N
CIJ=CIJ+A(I,K)*B(K,J)
10 CONTINUE
C(I,J)=CIJ
20 CONTINUE
RETURN
END
Subprogramul pentru calculul matricei inverse AINV a matricei A cu n linii și n coloane este:
SUBROUTINE INVMAT(A,AINV,N,IK)
ITER=0
Q=.01
EPS=.0001
CALL START(A,N,X0)
10 CALL UNIMT(N,U)
CALL PRMAT(A,X0,X1,N)
CALL SCMAT(UNIT,X1,DIF,N)
ITER=ITER+1
CALL PRMAT(DIF,X0,X1,N)
CALL ADMAT(X0,X1,X1,N)
CALL NMMAT(X0,N,ANOR)
IF(Q**ITER*ANOR/(1.-Q).LE.EPS) GO TO 20
CALL CPMAT(X1,X0,N)
GO TO 10
20 CONTINUE
CALL CPMAT(X1,AINV,N)
RETURN
END
Față de varianta inițială, aici sunt date valorile care dau finețea rezultatului, fără a da flexibilitate utilizatorului să obțină el precizia dorită, din dorința de a nu avea mulți paramertrii în listă.
(27 decembrie 2017)
Tuesday, December 26, 2017
Stabilirea tipului de triunghi
Dacă se dau numerele a,b și c trebuie văzut dacă acestea:
- sunt laturile unui triunghi;
- dacă este vorba de triunghi dreptunghic;
- dacă este vorba de triunghi isoscel;
- dacă este vorba de triunghi echilateral;
- dacă este vorba de triunghi oarecare.
Variabila IK=0 dacă a,b,b nu formează laturile unui triunghi, IK=1 dacă este vorba de un triunghi echilateral, IK=2 dacă este vprba de un triunghi dreptunghic oarecare, IK=3 dacă este un triunghi isoscel, IK=4 dacă este un triunghioarecare. IK=5 pentru variabile neinițializate corect.
Subprogramul este:
SUBROUTINE COMPAR (A,B,C,IK)
IF(A*B*C.LE.0) GO TO 5
IK=0
IK=0
IF(((A+B).LT.C).OR.((A+C).LT.B).OR.((B+C).LT.A)) GO TO 10
IK=1
IF((A.EQ.B).AND.(A.EQ.C).AND.(B.EQ.C)) GO TO 10
IK=2
IF(((A*A+B*B).EQ.(C*C)).OR.((A*A+C*C).EQ.(B*B)).OR.((C*C+B*B).EQ.(A*A))) GO TO 10
IK=3
IF((A.EQ.B).OR.(A.EQ.C).OR.(B.EQ.C)) GO TO 10
IK=4
IF((A+B).GT.C).OR.((A+C).GR.B).OR.((B+C).GR.A)) GO TO 10
5 IK=5
10 CONTINUE
RETURN
END
END
(26 decembrie 2017)
Factorial de n
A calcula un factorial de n înseamnă a calcula produsul Fn = 1*2*3*4*5*...*(n-1)*n. este important ca produsul să fie astfel calculat încât după efectuarea ultimei înmulțiri să nu depășească valoarea maximă a unui întreg ce se memorează pe 4 bytes adică 2.147.483.647 adică 2 la puterea 31 din care se scade 1, căci din cei 32 de biți unul este de semn, iar cel mai mare număr pozitiv are 0 pe prima poziție și 1 pe toate celelalte 31 de poziții, adică numărul scris de mine, adică două miliarde și ceva.
SUBROUTINE FACTOR (N,IFACT,IK)
IK=0.
IK=0.
IF(N.GT:xx) GO TO 20
FACT=1
DO 10 I=2,N
DO 10 I=2,N
FACT=FACT*I
10 CONTINUE
IK=1
20 CONTINUE
RETURN
END
END
Pentru a vedea cine este xx se va scrie un subprogram unde se lucrează cu variabile de tip real și se va identifica cel mai mare N care nu duce la valoarea unui factorial care să nu fie memorat ca un întreg de 4 bytes. Programul scris de mine arată că xx este undeva la 12. Cine dorește să calculeze factorial pentru numere mai mari trebuie să se consoleze să lucreze cu obținerea unui rezultat de tip real pe 8 bytes, care are un exponent ce nu depășește valoarea 10 la puterea 75 și numărul de cifre semnificative nu depășește 16, deci precizia are de suferit. E o întreagă discuție și aici, căci lucrurile mult mai bine precizate sunt dacă se lucrează în baza 16. Magnitudinea este 10 la puterea 63, iar precizia este de14 cifre hexazecimale, iar în baza 10 se fac aproximații.
(26 decembrie 2017)
Verificare dacă n este număr prim
Dacă se consideră un număr N se pune problema să se vadă dacă este sau nu număr prim. Acest lucru se realizează prin împărțiri succesive la numere impare mai mici decât radicalul numărului N. Dar ca să nu fie efort făcut fără rost se verifică mai întâi dacă N este număr par. Subprogramul returnează IK=0 dacă numărul N nu este număr prim și IK=1 dacă numărul N este număr prim.
SUBROUTINE COMPAR (N,IK)
IK=0
IK=0
IF(MOD(N,2).EQ.0) GO TO 20
A=N
M=SQRT(A)
DO 10 I=2,M
DO 10 I=2,M
IF(MOD(N,I).EQ.0) GO TO 20
10 CONTINUE
IK=1
20 CONTINUE
RETURN
END
END
(26 decembrie 2017)
Numărarea elementelor matricei
Una dintre cele mai simple probleme este aceea de a număra elementele pozitive, elementele nule și elementele negative dintr-o matrice A cu m linii și n coloane.
SUBROUTINE NUMAR (A,M,N,NRPOZ,NRNUL,NTNEG)
NRPOZ=0
NRPOZ=0
NRNUL=0
NRNEG=0
DO 40 I=1,M
DO 40 I=1,M
DO 40 J=1,N
IF(A(I,J)) 10,20,30
10 NRPOZ=NRPOZ+1
GO TO 40
20 NRNUL=NRNUL+1
GO TO 40
30 NRNEG=NRNEG+1
40 CONTINUE
RETURN
END
END
Acest text sursă scris în C++ arată cu mult mai elegant:
..................
nrpoz=nrnul=nrneg=0;
if(a[i][j]>0) nrpoz++;
else if(a[i][j]==0) nrnul++;
else nrneg++;
...................................
f[r[ niciun salt necondi'ionat ca ]n programul FORTRAN IV care are două, ceea ce justifică apropierea programatorilor de acest limbaj cu mult mai simplu și mai drăgălaș.
..................
nrpoz=nrnul=nrneg=0;
if(a[i][j]>0) nrpoz++;
else if(a[i][j]==0) nrnul++;
else nrneg++;
...................................
f[r[ niciun salt necondi'ionat ca ]n programul FORTRAN IV care are două, ceea ce justifică apropierea programatorilor de acest limbaj cu mult mai simplu și mai drăgălaș.
(26 decembrie 2017)
Concatenarea a două matrice
Condiția de a concatena matricele A și B este de a avea același număr de linii cadă prin concatenarea matricei B la matricea A înseamnă a lipi matricea B în dreapta matricei A. Dacă a concatena matricea B sub matricea A înseamnă că cele două matrice să aibe același număr de coloane. Prtopun ca prin concatenare să reculte o martrice C în care se copiază elementele matricelor A și B.
SUBROUTINE CONMTS (A,B,C,M,N)
SUMAT=0.
DO 10 I=1,M
SUMAT=0.
DO 10 I=1,M
DO 10 J=1,N1
10 C(I,J)=A(I,J)
10 C(I,J)=A(I,J)
DO 20 I=1,M
DO 20 J=1,N2
20 C(I,N1+J)=B(I,J)
20 C(I,N1+J)=B(I,J)
RETURN
END
END
Pentru concatenarea una sub alta:
SUBROUTINE CONMTS (A,B,C,M,N)
SUMAT=0.
DO 10 I=1,M1
SUMAT=0.
DO 10 I=1,M1
DO 10 J=1,N
10 C(I,J)=A(I,J)
10 C(I,J)=A(I,J)
DO 20 I=1,M2
DO 20 J=1,N
20 C(M1+I,J)=B(I,J)
20 C(M1+I,J)=B(I,J)
RETURN
END
END
Trebuie avut grijă la alocare ca matricea C să aibă suficiente linii sau coloane ca să suporte concatenarea.
(26 decembrie 2017)
Monday, December 25, 2017
Urma unei matrice
Urma unei matrice este suma elementelor de pe diagonala principală a matricei.
Urma unei matrice se realizează și folosind adunarea elementelor unui șir după ce se copiază elementele diagonalei principale a matricei într-un șir. Asta numai pentru a face reutilizare de cod.
SUBROUTINE ADMAT (A,M,N,URMA)
URMA=0.
DO 10 I=1,M
DO 10 I=1,M
10 URMA)=URMA+A(I,I)
RETURN
END
SUBROUTINE CPYDIA (A,M,N,X)
DO 10 I=1,M
10 X(I)=A(I,I)
RETURN
END
SUBROUTINE SUMSIR (X,N,SUMA)
SUMA=0.
SUMA=0.
DO 10 I=1,M
10 SUMA=SUMA+X(I)
RETURN
END
SUBROUTINE URMAT (A,M,N,URMA)
DIMENSION X(1)
CALL CPYDIA (A,M,N,X)
CALL SUMSIR (X,N,SUMA)
DIMENSION X(1)
CALL CPYDIA (A,M,N,X)
CALL SUMSIR (X,N,SUMA)
URMA=SUMA
RETURN
END
(26 decembrie 2017)
Sume pe coloane într-o matrice
Se consideră o matrice A cu m linii și n coloane și se pune problema caculului a n sume SUMCOL(J) cu j=1,2,3, ..., n pentru elementele de pe fiecare coloană.
(26 decembrie 2017)
SUBROUTINE ADMAT (A,B,C,M,N)
DO 10 J=1,N
DO 10 J=1,N
SUMCOL(J)=0.
DO 10 I=1,M
10 SUMCOL(J))=SUMCOL(J)+A(I,J)
10 SUMCOL(J))=SUMCOL(J)+A(I,J)
RETURN
END
END
sau ceva mai îmbunătățit din cauză că se referă o variab ilă elementară și nu una indexată ceea ce reduce numărul de cicluri mașină, numai că apar atribuiri în plus:
SUBROUTINE ADMAT (A,B,C,M,N)
DO 20 J=1,N
DO 20 J=1,N
SUMCOLJ=0.
DO 10 I=1,M
10 SUMCOLJ=SUMCOLJ+A(I,J)
10 SUMCOLJ=SUMCOLJ+A(I,J)
SUMCOL(J)=SUMCOLJ
20 CONTINUE
RETURN
END
Sume pe coloane în matrice se fac în multe calcule statistice, dar rezultatele apar într-o linie alăturată din matrice, m+1.
END
Sume pe coloane în matrice se fac în multe calcule statistice, dar rezultatele apar într-o linie alăturată din matrice, m+1.
SUBROUTINE ADMAT (A,B,C,M,N)
DO 20 J=1,N
DO 20 J=1,N
SUMCOLJ=0.
DO 10 I=1,M
10 SUMCOLJ=SUMCOLJ+A(I,J)
10 SUMCOLJ=SUMCOLJ+A(I,J)
A(M+1,J)=SUMCOLJ
20 CONTINUE
RETURN
END
END
Sume pe linii în matrice
Se consideră o matrice A cu m linii și n coloane și se pune problema caculului a m sume SUMLIN(I) cu i=1,2,3, ..., m pentru elementele de pe fiecare linie.
SUBROUTINE ADMAT (A,B,C,M,N)
DO 10 I=1,M
DO 10 I=1,M
SUMLIN(I)=0.
DO 10 J=1,N
10 SUMLIN(I)=SUMLIN(I)+A(I,J)
10 SUMLIN(I)=SUMLIN(I)+A(I,J)
RETURN
END
END
sau ceva mai îmbunătățit din cauză că se referă o variab ilă elementară și nu una indexată ceea ce reduce numărul de cicluri mașină, numai că apar atribuiri în plus:
SUBROUTINE ADMAT (A,B,C,M,N)
DO 20 I=1,M
DO 20 I=1,M
SUMLINI=0.
DO 10 J=1,N
10 SUMLINI=SUMLINI+A(I,J)
10 SUMLINI=SUMLINI+A(I,J)
SUMLIN(I)=SUMLINI
20 CONTINUE
RETURN
END
Sume pe linii în matrice se fac în multe calcule statistice, dar rezultatele apar într-o linie alăturată din matrice, coloana n+1.
SUBROUTINE ADMAT (A,B,C,M,N)
DO 20 I=1,M
DO 20 I=1,M
SUMLINI=0.
DO 10 J=1,N
10 SUMLINI=SUMLINI+A(I,J)
10 SUMLINI=SUMLINI+A(I,J)
A(I,N+1)=SUMLINI
20 CONTINUE
RETURN
END
(26 decembrie 2017)
Subscribe to:
Posts (Atom)

