typedef char CIFRE[50]; typedef REALE_ENORME struct { char Segno; CIFRE Decimale, Intera; };Sviluppiamo ora le varie funzioni che appaiono nell'interfaccia del modulo.
void Scrittura_Reale_Enorme(REALE_ENORME re) { int i, j; if(re.Segno == '-') Scrivi_Car('-');; for(i = 49; i >= 0 && re.Intera[i] == '0'; i--) ; if(i == -1) Scrivi_Car('0'); else for( ; i >= 0 ; i--) Scrivi_Car(re.Intera[i]); for(i = 49; i >= 0 && re.Decimale[i] == '0'; i--) ; if(i != -1){ Scrivi_Car(','); for( j = 0; j <=i ;j++) Scrivi_Car(re.Decimale[j]); } }
REALE_ENORME Leggi_Reale_Enorme(void) { CIFRE cif; int i,j; REALE_ENORME re; re.Segno = Leggi_Car(); if(re.Segno != '+' && re.Segno != '-') printf("ERRORE: un reale non puo\' iniziare con %c \n",re.Segno); Leggi_Cifre(cif,'\0'); /* le cifre intere sono messe in cif aggiungendo '\0' per completare vengono poi riordinate oppurtunamente quando ricopiate in re.Intera */ for(i=49; i >= 0 && cif[i] == '\0'; i--) re.Intera[i]= '0'; for(j = 0; i >= 0; i--,j++) re.Intera[j] = cif[ i]; Salta(','); Leggi_Cifre(re.Decimale,'0'); return re; }che utilizza la funzione ausiliaria
void Leggi_Cifre(CIFRE cif,char c) /*legge la sequenza di cifre decimali dal file `ingresso.txt' completa l'array con il carattere c*/ { int i; for(i=0; i < 50; i++) cif[i] = c; for(i = 0; (i < 50) && (isdigit(Guarda_Car())); i++) cif[i] = Leggi_Car(); }
REALE_ENORME Somma(REALE_ENORME re1, REALE_ENORME re2) { int j; REALE_ENORME re; if(re1.Segno == re2.Segno =='+'){ /*stesso segno*/ re = Somma_Pos(re1, re2); re.Segno = re1.Segno; } else if(Maggiore_Assoluto(re1, re2)){ /*re1 è maggiore in valore assoluto di re2*/ re = Differenza_Pos(re1, re2); re.Segno = re1.Segno; } else if(Maggiore_Assoluto(re2, re1)){ /*re2 è maggiore in valore assoluto di re*/ re = Differenza_Pos(re2, re1); re.Segno = re2.Segno; } else /* re conterrà 0 */ { re.Segno = '+'; for(j = 0; j < 50; j++) re.Decimale[j] = re.Intera[j] = '0'; }; return re; }che utilizza le seguenti funzioni ausiliarie
BOOL Maggiore_Assoluto(REALE_ENORME re1, REALE_ENORME re2) /*vera ses re1 è maggiore strettamente di re2*/ { int i, sono_uguali = TRUE; for(i = 49; sono_uguali && (0 *lt;= i); i--) if(re1.Intera[i] != re2.Intera[i]) sono_uguali = FALSE; if(! sono_uguali) return re1.Intera[i+1] > re2.Intera[i+1]; else{ /* controllo parti decimali*/ for(i=0; sono_uguali && i < 50; i++) if(re1.Decimale[i] != re2.Decimale[i]) sono_uguali = FALSE; if(! sono_uguali) return re1.Decimale[i-1] > re2.Decimale[i-1]; else return FALSE; }; } REALE_ENORME Somma_Pos(REALE_ENORME re1, REALE_ENORME re2) { int x, riporto = 0, i; REALE_ENORME re; for(i = 49; i >= 0; i--){ x = riporto + Num(re1.Decimale[i]) + Num(re2.Decimale[i]); if(x > 9){ re.Decimale[i] = Cifra(x % 10); riporto = 1; } else { re.Decimale[i] = Cifra(x); riporto = 0; }; }; for(i = 0; i < 50; i++){ x = riporto + Num(re1.Intera[i]) + Num(re2.Intera[i]); if(x > 9){ re.Intera[i] = Cifra(x % 10); riporto = 1; } else { re.Intera[i] = Cifra(x); riporto = 0; }; }; if(riporto == 1) printf("OVERFLOW\n"); return re; } char Cifra(int n) { return n + '0'; } int Num(char c) { return c - '0'; } REALE_ENORME Differenza_Pos(REALE_ENORME re1, REALE_ENORME re2) /*differenza tra due numeri positivi, quando il primo è maggiore del secondo */ { int x, riporto = 0, i; REALE_ENORME re; for(i = 49 ; i >= 0; i--){ if((Num(re1.Decimale[i]) + riporto) >= Num(re2.Decimale[i])){ re.Decimale[i] = Cifra((Num(re1.Decimale[i]) + riporto) - Num(re2.Decimale[i])); riporto = 0; } else{ re.Decimale[i] = Cifra((Num(re1.Decimale[i]) + riporto + 10) - Num(re2.Decimale[i])); riporto = -1; }; }; for(i = 0; i < 50 ; i ++){ if((Num(re1.Intera[i]) + riporto) >= Num(re2.Intera[i])){ re.Intera[i] = Cifra((Num(re1.Intera[i]) + riporto) - Num(re2.Intera[i])); riporto = 0; } else{ re.Intera[i] = Cifra((Num(re1.Intera[i]) + riporto + 10) - Num(re2.Intera[i])); riporto = -1; }; }; if(riporto == -1) printf("ERRORE : re1 doveva essere piu\' grande\n"); return re; };
REALE_ENORME Differenza(REALE_ENORME re1, REALE_ENORME re2) { re2.Segno = - re2.Segno; return Somma(re1, re2); }
in in-1 ... i1 i0, d0 d1 ... dm-1 dm
è uguale a
in* 10n + in-1* 10n-1 + ... + i1* 101 + i0* 100, d0* 101 + d1* 102 + ... + dm-1* 10m + dm* 10m+1
il prodotto è definito come segue:
REALE_ENORME Prodotto(REALE_ENORME re1, REALE_ENORME re2) { int i; REALE_ENORME aux,aux1, re; char seg; /* segno*/ seg = (re1.Segno == re2.Segno) ? '+' : '-'; /*rendo re1,e re2 positivi*/ re1.Segno = re2.Segno = '+'; /* assegno 0 a re */ for(i = 0 ; i < 50; i++) re.Intera[i] = re.Decimale[i] = '0'; /* moltiplico per cifre decimali */ for(i = 49 ; i >= 0 ; i--){ aux = Per_Scalare(re1, Num(re2.Decimale[i])); aux1 = Per_10(aux, -(i+1)); re = Somma(re, aux1); }; /* moltiplico per cifre intere */ for(i = 0 ; i < 50 ; i++){ aux = Per_Scalare(re1, Num(re2.Intera[i])); aux = Per_10(aux, i); re = Somma(re, aux); }; re.Segno = seg; return re; } REALE_ENORME Per_Scalare(REALE_ENORME re1, int n) { int riporto = 0, j, x; REALE_ENORME re; for(j = 49 ; j >= 0 ; j--){ x = riporto + (n * Num(re1.Decimale[j])); re.Decimale[j] = Cifra(x % 10); riporto = x / 10; }; for(j = 0 ; j < 50 ; j++){ x = riporto + (n * Num(re1.Intera[j])); re.Intera[j] = Cifra(x % 10); riporto = x / 10; }; if(riporto != 0) printf("OVERFLOW\n"); re.Segno = re1.Segno; return re; } REALE_ENORME Per_10(REALE_ENORME re1, int i) { REALE_ENORME re; int j; if(i == 0) return re1; else if(i > 0){ /* sposto indietro le vecchie cifre intere*/ for(j = 49 - i ; j >= 0 ; j--) re.Intera[j + i] = re1.Intera[j]; /* i cifre decimali diventano intere*/ for(j = 0; j <= i-1 ; j++) re.Intera[(i - 1) - j] = re1.Decimale[j]; /* sposto indietro le vecchie cifre decimali*/ for(j = i; j <= 49 ; j++) re.Decimale[j - i] = re1.Decimale[j]; /* aggiungo gli zeri decimali necessari */ for(j = (49-i) + 1; j <= 49 ; j++) re.Decimale[j] = '0'; re.Segno = re1.Segno; return re; } else /* i < 0 */ { i = -i; /* sposto le vecchie cifre decimali*/ for(j = 49 - i ; j >= 0 ; j--) re.Decimale[j + i] = re1.Decimale[j]; /* i cifre intere diventano decimali*/ for(j = 0; j <= i-1 ; j++) re.Decimale[ -j +(i -1)] = re1.Intera[j]; /* sposto le vecchie cifre intere*/ for(j = i; j <= 49 ; j++) re.Intera[j - i] = re1.Intera[j]; /* aggiungo gli zeri interi necessari */ for(j = 49-i+1; j <= 49 ; j++) re.Intera[j] = '0'; re.Segno = re1.Segno; return re; }; }