Sviluppo di REALI_ENORMI

Progettiamo una stuttura dati per i reali enormi.
Decidiamo di utilizzare 2 array, uno per le cifre (quindi caratteri) intere ed uno per quelle decimali, inoltre il numero sarà rappressentato utilizzando anche degli zeri inutili, pertanto ci saranno sempre 50 cifre intere e 50 cifre decimali.
Il segno sarà tenuto a parte.
Un reale enorme viene così realizzato:

La corrispondente dichiarazione di tipo C è
typedef char CIFRE[50];

typedef REALE_ENORME struct 
    {   char Segno;
        CIFRE Decimale, Intera;
    };
Sviluppiamo ora le varie funzioni che appaiono nell'interfaccia del modulo.
Stampa di un reale enorme
void Stampa_Reale_Enorme(REALE_ENORME re)
{   
    int i, j;

    if(re.Segno == '-')
        Print_Char('-');;
    for(i = 49; i >= 0 && re.Intera[i] == '0'; i--) ;
    if(i == -1) 
        Print_Char('0');
    else 
        for( ; i >= 0 ; i--) Print_Char(re.Intera[i]);
    for(i = 49; i >= 0 && re.Decimale[i] == '0'; i--) ;
    if(i != -1){
        Print_Char(',');
        for( j = 0; j <=i ;j++) Print_Char(re.Decimale[j]);
    }
}
Lettura di un reale enorme
REALE_ENORME Leggi_Reale_Enorme(void)
{  
    CIFRE cif;
    int i,j;
    REALE_ENORME re;
  
    re.Segno = Get_Char();
    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(Look_Char())); i++) 
       cif[i] = Get_Char();
}
Somma di due reali enormi
La somma di due numeri reali enormi re1 e re2 è definita come segue:
se re1 e re2 hanno lo stesso segno
segno di re1 (valore assoluto(re1) + valore assoluto(re2))
se re1 e re2 hanno segno diverso
se valore assoluto(re1) > valore assoluto(re2)
segno di re1 (valore assoluto(re1) - valore assoluto(re2))
se valore assoluto(re2) > valore assoluto(re1)
segno di re2 (valore assoluto(re2) - valore assoluto(re1))
se valore assoluto(re1) = valore assoluto(re2)
+ 0
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
int 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;
};
Differenza di due numeri reali
REALE_ENORME Differenza(REALE_ENORME re1, REALE_ENORME re2)
{
    re2.Segno = - re2.Segno;
    return Somma(re1, re2);
}
Prodotto di due numeri reali
Applicando la proprietà distributiva della somma rispetto al prodotto e notando che

è uguale a

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;

  };
}
A questo punto abbiamo sviluppato due file che faranno parte del programma, l'interfaccia e il body di questo modulo: REALENORME.h e REALENORME.c.