Showing posts with label software. Show all posts
Showing posts with label software. Show all posts

Friday, January 12, 2018

Ștefan MUSTĂȚEA, primul meu profesor de programare

Mustățea ȘTEFAN mi-a fost profesor de programarea calculatoarelor pe vremea în care eram student în anul al IV-lea la Secția de Mecanizare și Automatizare a Calculului Economic din Facultatea de Calcul Economic și Cibernetică Economică din Academia de Studii Economice, adică în anul universitar 1968 - 1969.
La cursul de Programarea calculatoarelor era profesor doctorul Dragoș VAIDA care lucra la Universitatea București. Practic și plastic vorbind, domnul Ștefan MUSTĂȚEA a fost acela care mi-a pus în mână creionul de programator. Ceea ce am remarcat la acest om se rezumă în următoarele cuvinte:
- era scump la vorbire, deci nu vorbea mult așa cum făceau profesorii din zona economicului;
- ceea ce avea de spus, spunea cu vorbe puține, clar și nu lăsa loc la interpretări;
- știa concret să programeze pe toate etapele ciclului de dezvoltare;
- venea din zona programării în cod mașină și se vedea că avea experiență adevărată.
Profesorul meu de atunci Mustățea ȘTEFAN, venea din zona programării în cod mașină și cu el am mers prima dată să văd cum funcționează calculatorul CIFA 102 în clădirea din Eminescu, unde acum se află Catedra de Informatică de Gestiune și unele dintre laboratoarele acesteia. Îmi aduc aminte și acum, după atâțea ani cum enunța el o problemă, cum explica pas cu pas despre alegerea variabilelor și cum se construiște schema logică pentru a rezolva problema. De la schema sa logică pleca spre program, cu utilizarea de regiștrii, cu instrucțiunile elementare și cu explicațiile de cum trebuie perforate pe bandă de hârtie acele instrucțiuni. Misterul lucrului pe un calculator electronic din prima generație l-am dezlegat datorită profesorului meu de atunci, Mustățea ȘTEFAN, care venea direct din laborator, îmbrăcat cu galatul său alb din material sintetic.
Ani în șir l-am urmărit cu admirație pe domnul Mustățea ȘTEFAN, bărbatul înalt, zvelt, drept, cu mersul apăsat, cu privire ageră și cu vorbă măsurată. Dacă avea să se adreseze cumva o făcea cu cuvântul acela des utilizat în vremurile de demult, tovule, dar niciodată nu spunea decât ceea ce era absolut necesar și într-o manieră care impunea respect.
Știam despre domnul Mustățea ȘTEFAN că este absolvent de matematică, știam că avea în spate perfecționări în programare, inclusiv în Japonia la firma NEAC de unde a și fost cumpărat un calculator pe care tot în anul al IV-lea am lucrat în limbajul COPCODER. Când aveam de studiat ceva, mergeam în biblioteca tehnică a Laboratoarelor Catedrei de Cibernetică Economică - LCCE,  unde găseam printre documentații de firmă materiale elaborate de Mustățea ȘTEFAN în colaborare cu tinerii cu care lucra și am multe exemple de materiale elaborate de acesta împreună cu Anca ANDREI și cu Ioan ODĂGESCU, dar și multe articole publicate în revista Studii și Cercetări de Calcul Economic și Cibernetică Economică, a cărei variantă în limba engleză este ISI catalogată și cu care toată lumea se mândrește. Amintesc aici lucrările referite prin:
Stefan MUSTATEA, Ion ODAGESCU - Programarea calculatoarelor electronice - FORTRAN IV - culegere de probleme rezolvate si propuse, Litografia ASE, Bucuresti, 1973, 296pg.
Ștefan MUSTĂȚEA, Dan SOMNEA, Mircea PĂTRULESCU - Sistemul dBASE II, prezentare, utilizare, studiu de caz, partea a I-a și partea a II-a, Studii și Cercetări de Calcul Economic și Cibernetică Economică, vol. 22, n2. 2 și nr, 3, 1987.
După decembrie 1989 fostul meu profesor Ștefan MUSTĂȚEA a susținut cu succes o teză de doctorat intitulată Gestiunea optimă a materialelor, la nivelul unei unități economico-sociale, folosind calculatoare electronice. În timp, activitatea din Laboratoarele Catedrei de Cibernetică Economică s-a restrâns treptat din lipsa contractelor cu industria intrată în degringoladă, mai ales după ce premierul o catalogase drept grămadă de fier vechi și nu am mai avut ocazia să-l întâlnesc pe fostul meu profesor Ștefan MUSTĂȚEA. Am înțeles că a plecat din țară, dar uneori când revenea megrea să se reîntâlnească cu locurile unde și-a desfășurat zeci de ani din activitatea profesională, prilej cu care l-am reîntâlnit și cu același respect am discutat despre vremurile de pionierat ale informaticii din țara noastră, el fiind un actor important, căci fără programatorii profesioniști ai primelor generații de calculatoare în niciun caz nu s-ar vorbi despre o informatică autentică având temelii solide și rezultate de început foarte valoroase, cu programe folosite efectiv în întreprinderi.
În primăvara anului 2017 fostul meu profesor a avut o alocuțiune, pe care o redau exact așa cum autorul ei mi-a încredințat-o, alocuțiune care în opinia mea este o radiografie a informaticii economice românești care se suprapune cu activitatea laboratoarelor Centrului de Calcul al ASE.





(12 ianuarie 2018)

Lungime sau volum de prelucrări

Când se scrie un program se fac multe calcule pentru a vedea care este varianta de program cea mai convenabilă. Se fac alegeri justificate cu destul de multe argumente, unele fiind foarte convingătoare. De regulă se construiesc modele de eficiență în care apar inegalități din care să rezulte când este bună o variantă și când este bună o altă variantă de program. Voi da un exemplu de astfel de analiză. Există o problemă P în care trebuie evaluate expresiile:
C = A + B
P = R + S
X = Y + Z
W = U + V
unde A, B, C, P, R, S, X, Y, Z, W, U și V sunt matrice cu diferite dimensiuni care permit totuși efectuarea operațiilor specifice acelor expresii, adică matricele A, B, C au fiecare M1 linii și N1, coloane, matricele P, R, S au fiecare câte M2 linii și N2 coloane, matricele X, Y, Z au fiecare M3 linii și N3 coloane, iar matricele W, U și V au respectiv M4 linii  și N4 coloane. Ideia de bază care se desprinde este aceea de a scrie un subprogram de adunare a două matrice, subprogram care va fi apelat de 4 ori, ceea ce duce la textul sursă următor:

            SUBROUTINE ADMAT(A,B,C,M,N)
            DO 10 I=1,M
            DO 10 J=1,N
            C(I,J)=A(I,J)+B(I,J)
10        CONTINUE
            RETURN
            END
Programul principal va conține:

................. secvență inițializare variabile M1, N1, M2, N2, M3, N3, M4, N4 .............
................. secvență inițializare matrice A, B .............
................. secvență inițializare matrice R, S .............
................. secvență inițializare matrice Y, Z .............
................. secvență inițializare matrice U, V .............
            CALL ADMAT(A,B,C,M1,N1)
            CALL ADMAT(R,S,P,M2,N2)
            CALL ADMAT(Y,Z,X,M3,N3)
            CALL ADMAT(U,V,W,M4,N4)
................. secvență cu alte prelucrări ale matricelor C, P, X și W.
Pentru ceea ce ne interesează să se optimizeze, textul sursă se referă la o construcție de lungime
Lg = 6 + 4 = 10 instrucțiuni ( instrucțiuni pentru subprogram și 4 instrucțiuni pentru apelul subprogramului ADMAT(...).
Dacă se încorporează toate secvențele în programul principal, acesta va arăta astfel:

................. secvență inițializare variabile M1, N1, M2, N2, M3, N3, M4, N4 .............
................. secvență inițializare matrice A, B .............
................. secvență inițializare matrice R, S .............
................. secvență inițializare matrice Y, Z .............
................. secvență inițializare matrice U, V .............
            DO 10 I=1,M1
            DO 10 J=1,N1
            C(I,J)=A(I,J)+B(I,J)
10        CONTINUE
            DO 10 I=1,M2
            DO 10 J=1,N2
            P(I,J)=R(I,J)+S(I,J)
20        CONTINUE
            DO 10 I=1,M3
            DO 10 J=1,N3
            X(I,J)=Y(I,J)+Z(I,J)
30        CONTINUE
            DO 10 I=1,M4
            DO 10 J=1,N4
            W(I,J)=U(I,J)+V(I,J)
40        CONTINUE
................. secvență cu alte prelucrări ale matricelor C, P, X și W.
Această variantă are lungime Lg = 16 instrucțiuni. Programul în prima variantă are la execuție pentru cele patru apeluri de subprograme grupul de operații complexe:
- o instrucțiune de salt necondiționat spre subprogram;
- estragere de pe stivă a adreselor operanzilor;
- execuția adunării elementelor matricelor;
- revenirea în programul apelator.
La fiecare apel volumul de prelucrări este undeva la 7 instrucțiuni, deci ceea ce părea o economie se concretizează prin 28 de instrucțiuni, dintre care unele sunt costisitoare la ciclurile mașină dacă salturile necondiționate se fac intersegment când suprogramul se află în alt segment decât programul apelator. Este o întreagă filosofie a discuta despre echilibrul lungime program și volum de prelucrări și totul se rezolvă prin măsurători de ordin statistic, adevărul fiind undeva la jumătate.

(12 ianuarie 2017)


Sunday, January 7, 2018

Generare n numere prime

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)       


Saturday, December 30, 2017

Fiabilitatea programelor și ordinele de mărime

În programele FORTRAN IV se lucra cu:
- variabile și constante de tip întreg definite pe 4 bytes;
- variabile și constante de tip real definite pe 4 bytes;
- variabile și constante de tip real definite pe 4 bytes;
- variabile și constante de tip logic
- variabile și constante de tip complex definite pe 4+4 bytes.
Fiecare constantă sau variabilă este caracterizată prin magnitudine, adică valoare maximă, respectiv, valoare minimă și prin ordin de mărime, adică număr de cifre maxim ce se stochează în zona de memorie care se alocă.
O constantă de tip întreg care este definită pe 4 bytes are cel mai mare număr ce se stochează acolo egal cu 2 la puterea 31 minus 1, cunoscătorii știu de ce..., adică magnitudinea maximă este de 2147483647. Deci dacă cineva dorește să scrie un program fiabil în care adună două numere IA și IB trebuie să verifice dacă:
  • IA > 2147483647;
  • IB > 2147483647;
  • IA+IB > 2147483647.
Având în vedere că în calcule toate variabilele sunt cu aceeași importanță, este rezonabil să se ia în considerare pentru fiecare dintre ele un domeniu care să asigure fiabilitatea programului în orice condiții. Din punctul meu de vedere, domeniul de variație al variabilelor nu trebuie calculat pe bucățele, ci per global, pentru a da generalitate și operaționalitate programului, adică programul să funcționeze în orice condiții, nu uneori da și de o mie de ori, nu.
Dacă se consideră doi operanzi de tip întreg OP1 și OP2 având N1 și respectiv N2 cifre, când se face o operație de adunare sau de scădere rezultatul REZ = OP1 + OP2  va avea un număr de cifre egal cu NREX = max (N1,N2) +1. Ca un program să fie fiabil trebuie ținut seama și de acest aspect. Dacă rezultatul REZ nu trebuie să fie mai mare în valoare absolută decât 2147483647, înseamnă că operanzii OP1 și OP2 nu trebuie să fie mai mari în valoare absolută decât 2147483647/2, adică mai mare decât 1072418237. Sunt chestiuni învățate în școala elementară, despre care foarte mulți dintre noi nu le-am considerat importante atunci, dar care pentru a face programe fiabile revin în forță.
Dacă se consideră doi operanzi de tip întreg OP1 și OP2 având N1 și respectiv N2 cifre, când se face o operație de înmulțire rezultatul REZ = OP1 * OP2  va avea un număr de cifre egal cu NREX =  N1+N2. În acest context OP1 și OP2 nu trebuie să fie mai mari de 46340 pentru a nu avea dureri de cap cu derularea calculelor și fără a fi nevoiți să stabilim numărul de cifre al numărelor stocate în zonele de memorie OP1 sau OP2.
Este rezonabil să introducem prin programele noastre colo și colo instrucțiuni precum:
                  IF((OP1.GT.1072418237).OR.(OP2.GT.1072418237)) GO TO 10
                  REZ = OP1 + OP2
                  IK=1
sau
                  IF((OP1.GT.46340).OR.(OP2.GT.46340)) GO TO 10
                  REZ = OP1 * OP2
                  IK=2
....................
10              IK=0
....................
Unde IK=0 dacă operațiile de calcul nu se efectuează din motive de depășire a capacității sau IK=1 în ideia că operațiile se efectuează. Dacă suntem convinși că trebuie să verificăm efectuarea calculelor se vor face conversii pe real a operanzilor și numai după efectuarea calculelor finale se va face testul dacă rezultatul final este mai mare decât constanta reală 2147483647. ceea ce va conduce la atribuirea valorii IK=0 cum că s-a produs o depășire care duce la trunchiere dacă se face conversie de la real spre întreg.
Fiabilitatea programelor și ordinele de mărime merg mână în mână și în vremurile de demult subdepășirea dar și depășirea de capacitate au dat mari bătăi de cap programatorilor mai ales când erau neglijeate oarece inițializări și se lucra cu operanzii neinițializați spre direcționarea în zone aleatoare a rezultatelor finale.




(30 decembrie 2017)

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 

Image result for linear regression formula












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)


     

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
         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

(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.
         IF(N.GT:xx) GO TO 20
         FACT=1
         DO 10 I=2,N
         FACT=FACT*I
10     CONTINUE
         IK=1
20     CONTINUE
         RETURN
         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
         IF(MOD(N,2).EQ.0) GO TO 20
         A=N
         M=SQRT(A)
         DO 10 I=2,M
         IF(MOD(N,I).EQ.0) GO TO 20
10     CONTINUE
         IK=1
20     CONTINUE
         RETURN
         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
         NRNUL=0
         NRNEG=0
         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
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ș.


(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
         DO 10 J=1,N1
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)
         RETURN
         END
Pentru concatenarea una sub alta:
         SUBROUTINE CONMTS (A,B,C,M,N)
         SUMAT=0.
         DO 10 I=1,M1
         DO 10 J=1,N
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)
         RETURN
         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.
         SUBROUTINE ADMAT (A,M,N,URMA)
         URMA=0.
         DO 10 I=1,M
10     URMA)=URMA+A(I,I)
         RETURN
         END

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 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.         
         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)       
         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ă.

         SUBROUTINE ADMAT (A,B,C,M,N)
         DO 10 J=1,N
         SUMCOL(J)=0.
         DO 10 I=1,M
10     SUMCOL(J))=SUMCOL(J)+A(I,J)
         RETURN
         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
         SUMCOLJ=0.
         DO 10 I=1,M
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.
         SUBROUTINE ADMAT (A,B,C,M,N)
         DO 20 J=1,N
         SUMCOLJ=0.
         DO 10 I=1,M
10     SUMCOLJ=SUMCOLJ+A(I,J)
         A(M+1,J)=SUMCOLJ
20     CONTINUE

         RETURN
         END


(26 decembrie 2017)                    

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
         SUMLIN(I)=0.
         DO 10 J=1,N
10     SUMLIN(I)=SUMLIN(I)+A(I,J)
         RETURN
         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
         SUMLINI=0.
         DO 10 J=1,N
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
         SUMLINI=0.
         DO 10 J=1,N
10     SUMLINI=SUMLINI+A(I,J)
         A(I,N+1)=SUMLINI
20     CONTINUE

         RETURN
         END


(26 decembrie 2017)

Inserarea unui element în șir

Inseraea unui element din șir

Se consideră șirul x1, x2, x3, ..., xk, ...., xn cu n componente și se pune problema inserării unui element VAL pe 
poziția k din șir, ceea ce va duce la faptul că șirul va avea n+1 elemente după aceea. 
Subprogramul verifică dacă poziția elementului ce trebuie șters este în șir. Variabila de stare IK=1 dacă 
ștergerea s-a efectuat sau IK=0 în caz contrar din cauză că elementul ce trebuie șters nu se află în interiorul 
șirului. Noul șir are NN componente. Se adoptă convenția că șirul X rămâne neschimba, iar șirul cu elementul inclus este
Y cu n+1 componente.

         SUBROUTINE MAXIM (X,Y,N,K, NN, IK)
         IK=0
         IF(K.LT.1.OR.K.GT.N) GO TO 20
         DO 10 I=1,K-1
         Y(I)=X(I)
10     CONTINUE
         Y(K)=VAL
         DO 10 I=K,N
         Y(I+1)=X(I)
10     CONTINUE
         IK=1
         NN=N+1
20     CONTINUE
         RETURN
         END



(24 decembrie 2017)

Interschimb a două linii din matrice

Fiind dată matricea A cu m linii și n coloane se pune problema interschimbului dintre coloanele ICOL1 și ICOL2.


         SUBROUTINE ADMAT (A,M,N,LIN1,LIN2)
         DO 10 J=1,N
         AUX=A(LIN1,J)
         A(LIN1,J)=A(LIN2,J)
         A(LIN2,J)=AUX
10     CONTINUE
         RETURN
         END
Sublrogramul dacă verifică dacă ICOL1 și ICOL2 sunt valori în afara matricei mai presupune definirea unei variabile IK =0 dacă valorile sunt incorecte, adică sunt fie negative, fie mai mari decât numărul de linii ale matricei și IK=1 dacă valorile sunt corecte și s-a săcut interschimbul.


         SUBROUTINE ADMAT (A,M,N,LIN1,LIN2, IK)
         IK=0
         IF((LIN1.LE.0).OR.(LIN1.GT.M).OR.(LIN2.LE.0).OR.(LIN2.GT.M)) GO TO 20
         DO 10 J=1,N
         AUX=A(LIN1,J)
         A(LIN1,J)=A(LIN2,J)
         A(LIN2,J)=AUX
10     CONTINUE
         IK=1
20     RETURN
         END

(25 decembrie 2017)