Lezione in Aula del 23 Ottobre 2001 & lezioni in laboratorio nel corso della stessa settimana

L'astrazione procedurale


COSA E' STATO FATTO A LEZIONE

Questo documento contiene un RIASSUNTO degli argomenti presentati a lezione. Per eventuali chiarimenti rivolgersi ai docenti.

Un semplice problema

Problema:Scrivere un programma Java che legga da terminale due numeri interi B, E e scriva su teminale il valore B^E (B elevato ad E).

(ATTENZIONE: si richiede di NON usare la classe Math della libreria Java).

Soluzione:

  1. Gli interi menzionati nel testo del problema saranno memorizzati in variabili di tipo "int".
  2. Il programma sara' costituito da due "componenti":


    PRIMA COMPONENTE.
    La prima componente sara' costituita da due files: il file AConsoleReader.java (gia' utilizzato nelle lezioni precedenti), e il file TextExp.java che conterra' una sola classe, il cui unico metodo sara' "main", che si occupera' di: leggere B ed E da terminale, richiedere all'altra componente di effettuare il calcolo di B^E, e scrivere il risultato sul terminale.


    SECONDA COMPONENTE.
    La seconda componente sara' costituita da un solo file: il file MyMath.java, che conterra' un solo metodo, con la seguente intestazione:

    /*
       AI: b != 0 AND e >= 0
       AF: restituisce  b^e
    */
    public static int myExp(int b, int e)
    

    I commenti che precedono l'intestazione del metodo sono detti "Asserzione Iniziale" (AI) e "Asserzione Finale" (AF). Essi rappresentano una sorta di "contratto" tra chi scrive il codice del metodo "myExp" e chi lo usa.
    L'AI specifica quali condizioni devono soddifare gli argomenti che vengono passati al metodo al momento della chiamata (il metodo e' stato pensato per operare su argomenti che soddisfano tali condizioni). E' compito di chi usa il metodo garantire che il metodo sia chiamato in modo corretto.
    L'AF specifica quale condizione soddisfera' il valore restituito dal metodo (o piu' in genearale quali saranno gli effetti dell'esecuzione del metodo) SE gli argomenti soddisfano l'AI. Ovviamente, e' compito di chi scrive il metodo garantire che il metodo sia corretto (cioe' rispetti quando affermato nel "contratto").

    L'utilizzo di AI e AF permette di "dividere" (in modo controllato) un unico programma in diverse "componenti" che possono essere realizzate da persone diverse.

    Se:

    Allora: sara' possibile combinare tra di loro le diverse componenti senza problemi. Inoltre, in un qualunque momento una componente potra' essere rimpiazata da un'altra componente che rispetti la stessa "specifica".

  3. INTERAZIONE TRA LE DUE COMPONENTI
    La prima componente invochera' il metodo myExp della classe MyMath con un'istruzione del tipo:
    // a != 0 AND b >= 0
    c = MyMath.myExp(a,b);
    // c = a^b
    
    dove a, b, c sono variabili di tipo int.

    Le asserzioni che precedono e seguono l'invocazione del metodo sono dei semplici "pro-memoria" per quanto scritto nella specifica del metodo. Se il metodo rispetta la sua specifica e l'asserzione che precede l'invocazione del metodo e' vera, allora anche l'asserzione che segue l'invocazione del metodo e' vera.

  4. SVILUPPO DELLA PRIMA COMPONENTENTE

    Lo sviluppo di tale componente e' non presenta particolari difficolta' (vedi lezioni precedenti), passiamo quindi ad esaminare la seconda componente.

  5. SVILUPPO DELLA SECONDA COMPONENTENTE

    Siano B="valore iniziale di b" e E="valore iniziale di e".
    Dall'AI sappiamo che: A !=0 e B >=0.
    Possiamo quindi calcolare B^E osservando che:

    B^E = B * B * ... * B 
         |               |
          ---------------
             (E volte)
    
    Il body del motodo "myExp" potra' quindi essere il seguente:
       {  int r=1; // il valore da restituire
          int i=0; // indice sull'intervallo 0..e
    
          // 0<=i<=e AND  r=b^i
          while (i < e)
          {  r *= b; 
             i++;
          }
    
          // r =  b^e
          return e;
    

    Oppure, se preferiamo il for:

       {  int r=1; // il valore da restituire
    
          // 0<=i<=e AND  r=b^i
          for (i=0; i < e; i++)
             r *= b; 
    
          // r =  b^e
          return e;
    

    ESERCIZI DA SVOLGERE (assegnati al termine della Lezione in Aula)

    Il primo esercizio e' semplice routine. Il secondo e' abbastanza facile. Il terzo e il quarto sono piuttosto difficili.

    LA SOLUZIONE DEGLI ULTIMI TRE ESERCIZI SARA' PRESENTATA DURANTE LA PROSSIMA LEZIONE IN AULA (Martedi' 30, alle 11:00 in Aula B).

    Per eventuali chiarimenti rivolgersi ai docenti.

    1. Scrivere i sorgenti Java che realizzano la soluzione (descritta all'inizio di questo documento) del problema:

      Scrivere un programma Java che legga da terminale due numeri interi B, E e scriva su teminale il valore B^E (B elevato ad E).

      Compilare ed eseguire il codice.

    2. Algoritmo per il calcolo fattoriale
      Per ogni numero intero n>=0, il "fattoriale di n" e' il numero:
      n! = n*(n-2)*...*3*2*1. 
      

      In particolare: 0! = 1.

      Aggiungere alla classe MyMath un metodo:

      public static int myFact(int n)
      
      tale che, per ogni m>=0, MyMath.myFact(m) restituisca m! (NOTA:si richiede di corredare l'intestazione del metodo di "Asserzione Iniziale" e "Asserzione Finale", e di inserire nel codice l'eventuale "Invariante di Ciclo".)
    3. Algoritmo per il calcolo dell'n-esimo numero di Fibonacci.
      In numeri calcolati in base alla seguente formula:
      F(0) = 0
      F(1) = 1
      F(n) = F(n-1) + F(n-2)
      
      sono noti come "numeri di fibonacci". Lo 0-esimo numero di Fibonacci e' 0, l'1-esimo e' 1, il 2-esimo e' 1, il 3-esimo e' 2, etc.

      Aggiungere alla classe MyMath un metodo:

      public static int myFib(int n)
      
      tale che, per ogni m>=0, MyMath.myFib(m) restituisca l'm-esimo numero di Fibonacci (NOTA:si richiede di corredare l'intestazione del metodo di "Asserzione Iniziale" e "Asserzione Finale", e di inserire nel codice l'eventuale "Invariante di Ciclo".)
    4. Versione migliorate del metodo "myExp"
      Dati due numeri interi b>0, e>=0, utlizzare le ugualianze:
      b^0  = 1
      b^(2*e) = (b*b)^e
      b^(2*e+1) = b*b^(2*e)
      
      per scrivere una versione piu' efficiente del metodo per il calcolo dell'esponenziale. (NOTA:intestazione del metodo, "Asserzione Iniziale" e "Asserzione Finale" sono quelle del metodo "myExp" descritto in precedenza. Si richiede di inserire nel codice l'eventuale "Invariante di Ciclo".)

    COSA SI DEVE LEGGERE (sul libro di testo)

    Questa settimana non vengono assegnate "letture" per la parte di laboratorio. LEGGETE PERO' LE PARTI DI LIBRO INDICATE ALLA PAGINA DEL Programma delle Lezioni tenute dal prof. Martelli .