Corso di Java per la 3 E Sia - 5a Lezione 30 gennaio 2016 ore 11,00

Corso di Java per la 3 E Sia - 
5a Lezione 30 gennaio 2016 ore 11,00
Array
Array: introduzioneUn array è un gruppo di variabili dello stesso tipo. Per esempio, un array di interi è un gruppo di variabili, tutte di tipo intero. Il vantaggio dell'array è che basta una sola dichiarazione, ed è facile realizzare dei cicli che effettuano le stesse operazioni su tutte le variabili di un vettore. Si consideri per esempio la situazione in cui si hanno 100 valori interi, e a un certo punto è necessario incrementare ognuno di essi di 1 e stamparli. 



Senza usare i vettori, sarebbe necessario un codice complicato come quello del programma NoArray.java:
class NoArray {
  public static void main(String[] args) {
    int variabile1=41;
    int variabile2=74;
    int variabile3=7;
    ....

    variabile1=variabile1+1;
    System.out.println(variabile1);
    variabile2=variabile2+1;
    System.out.println(variabile2);
    variabile3=variabile3+1;
    ...
  }
}
Questo genere di operazioni si semplificano raggruppando tutte le variabili di un certo tipo in un unico vettore. La dichiarazione di un vettore che contiene 100 elementi di tipo intero è:
  int x[]=new int[100];
Si può pensare a questa operazione come equivalente a dichiarare le seguenti variabili, tutte di tipo intero: x[0], x[1], x[2],...., x[99]. Si noti che il primo elemento è 0, mentre l'ultimo è 99. Questo può creare confusione, dal momento che nella dichiarazione appare il numero 100.
Il punto fondamentale è che queste variabili x[0],... si possono usare come variabili normali, ma in più è possibile anche fare riferimenti per esempio a x[i] dove i è un'altra variabile. Per esempio, la sequenza di istruzioni
i=10;
System.out.println(x[i]);
stampa il contenuto della variabile x[10]. In generale, la notazione x[espressione] è la componente del vettore determinata dalla valutazione della espressione. Se per esempio i=10 allora x[i+4]è esattamente lo stesso di x[14]. Questo rende i vettori molto comodi quando ci sono operazioni che vanno ripetute su un insieme di variabili. Per esempio, l'incremento e stampa dei cento valori si può fare definendo e assegnando valori a un vettore di interi x, e poi effettuando un ciclo:
  int i;

  for(i=0; i<=99; i=i+1) {
    x[i]=x[i]+1;
    System.out.println(x[i]);
  }
La assegnazione agli elementi di un vettore si può semplificare. Invece di fare x[0]=41; x[1]=74; ..., si possono dare tutti i valori nella fase di dichiarazione. Il programma completo ConArray.java è il seguente.
class ConArray {
  public static void main(String[] args) {
    int x[]={41, 74, 7, 40, 73, 6, 39, 72, 5, 38, 71, 4, 37, 70, 3, 36, 69, 2, 35, 68, 1, 34, 67, 0, 33, 66, 99, 32, 65, 98, 31, 64, 97, 30, 63, 96, 29, 62, 95, 28, 61, 94, 27, 60, 93, 26, 59, 92, 25, 58, 91, 24, 57, 90, 23, 56, 89, 22, 55, 88, 21, 54, 87, 20, 53, 86, 19, 52, 85, 18, 51, 84, 17, 50, 83, 16, 49, 82, 15, 48, 81, 14, 47, 80, 13, 46, 79, 12, 45, 78, 11, 44, 77, 10, 43, 76, 9, 42, 75, 8, 41 };
    int i;

    for(i=0; i<=99; i=i+1) {
      x[i]=x[i]+1;
      System.out.println(x[i]);
    }
  }
}

Dimensione di un vettore

Concludiamo la sezione con il metodo che permette di valutare la lunghezza di un vettore. Nel caso in cui il vettore venga dichiarato con una istruzione del tipo int x[]=new int[100], questo vettore contiene esattamente 100 elementi (da 0 a 99) ossia il numero di elementi è dato dal numero fra parentesi quadre. Nel caso in cui la dichiarazione contiene già la inizializzazione, ossia del tipo int x[]={12, 24, ...}, il numero di elementi che compongono un vettore è dato dal numero di elementi fra parentesi graffe. Esiste un modo per determinare la lunghezza di un vettore senza contare gli elementi nella dichiarazione: se x è un vettore, allora x.length è la sua lunghezza. Quindi, una istruzione del tipo System.out.println(x.length) stampa il numero di elementi del vettore x.

Indici di un vettore

Come si è già specificato, gli elementi di un vettore x sono x[0], ecc, fino a un certo x[c], in cui c dipende dalla dichiarazione del vettore. Cosa succede se si prova a usare x[d] in cui d>c? Durante la esecuzione del programma si genera un errore. Lo stesso succede usando un d negativo. In generale, se un vettore ha elementi x[0],...,x[c], ogni tentativo di usare elementi x[d] in cui d non è compreso fra 0 e c genera un errore.
Per concludere, va notato come l'indice di un vettore (quello che sta fra parentesi quadre) può essere una espressione qualsiasi purchè dia un risultato di tipo intero, oltre che compreso fra 0 e il massimo elemento del vettore. Esemi di riferimenti che non funzionano sono:
  1. x[10.5] (perchè 10.5 è un numero reale)
  2. x[i] (dove i è una variabile reale)

Massimo elemento di un vettore

Questo esercizio consiste nel trovare, in un vettore di interi, quello che ha valore massimo. Si inizia con la definizione del vettore e dei sui valori:
class Massimo {
  public static void main(String[] args) {
    int x[]={12, 45, 78, 11, 44, 77, 10, 43, 76, 9, 42, 75, 8, 41, 74, 7, 40, 73 , 6, 39, 72, 5, 38, 71, 4, 37, 70, 3, 36, 69, 2};
La prima cosa da fare è determinare il numero di elementi di cui il vettore è composto. Contare tutti gli elementi a mano richiede tempo. Inoltre, ogni volta che si deve aggiungere un nuovo valore al vettore, occorre modificare il codice per tenere conto dell'aumento o diminizione del numero di elementi. Per questa ragione, definiamo una variabile nella quale mettiamo il numero di elementi:
    numeroelementi=x.length;
Per calcolare il massimo, seguiamo l'algoritmo per cui assumiamo inizialmente che il massimo elemento è il primo, e poi facciamo una scansione degli elementi del vettore. Se troviamo un elemento che è maggiore del massimo, quello è il nuovo massimo. In altre parole:
  1. il massimo elemento è il primo;
  2. per ogni valore di i:
    • se x[i] è maggiore del massimo trovato finora,
    • allora x[i] è il nuovo massimo.
In termini di codice, il primo passo si traduce in:
    massimo=x[0];
Mentre il ciclo diventa:
    for(i=0; i<=numeroelementi-1; i=i+1) {
      if( x[i]>massimo ) {
        massimo=x[i];
      }
    }
Si noti che gli elementi del vettore partono da x[0]. Il vettore ha numeroelementi componenti, per cui l'ultimo elemento è x[numeroelementi-1]. Questo è il motivo per cui il ciclo deve partire dal valore 0 e arrivare al valore numeroelementi-1.
Alla fine della iterazione la variabile massimo contiene il valore del massimo elemento del vettore. Il programma completo è Massimo.java, in cui al posto della variabile numeroelementi si usa direttamente x.length come valore finale del ciclo for.
/*
  Trova il massimo elemento di un vettore.
*/

class Massimo {
  public static void main(String[] args) {
    int x[]={12, 45, 78, 11, 44, 77, 10, 43, 76, 9, 42, 75, 8, 41, 74, 7, 40, 73, 6, 39, 72, 5, 38, 71, 4, 37, 70, 3, 36, 69, 2};
    int i;
    int massimo;

    massimo=x[0];

    for(i=0; i<=x.length-1; i=i+1) {
      if( x[i]>massimo ) {
        massimo=x[i];
      }
    }

    System.out.println("Il massimo e' "+massimo);
  }
}

Somma elementi di un vettore

Sia dato un vettore; si vuole la somma di tutti i suoi elementi. Questo esercizio non differisce molto da quello del calcolo della somma degli elementi di una serie: si tratta infatti di sommare un certo numero di elementi fra di loro. Nel caso della somma della serie questi elementi erano determinati dalla funzione, mentre ora ogni elemento è una componente x[i] del vettore.
Lo svolgimento è lo stesso: usiamo una variabile somma per memorizzare la somma degli elementi analizzati fino ad ora. Inizialmente la somma vale 0. Si fa poi un ciclo in cui, ad ogni passo, si prende un elemento del vettore e lo si aggiunge al contenuto della variabile somma. Il programma completo è SommaVettore.java, di cui si riporta il codice qui sotto.
/*
  Somma gli elementi di un vettore.
*/

class SommaVettore {
  public static void main(String[] args) {
    int x[]={32, 65, 98, 31, 64, 97, 30, 63, 96, 29, 62, 95, 28, 61, 94, 27, 60, 93, 26, 59, 92, 25, 58, 91, 24, 57, 90, 23, 56, 89, 22, 55, 88, 21, 54, 87, 20, 53, 86, 19, 52, 85, 18, 51, 84, 17, 50, 83, 16, 49, 82};
    int i;
    int somma;

    somma=0;

    for(i=0; i<=x.length-1; i=i+1) {
      somma=somma+x[i];
    }

    System.out.println("La somma vale: "+somma);
  }
}

Media elementi di un vettore

Dato un vettore di interi, si vuole calcolare il loro valore medio. Come è noto, il valore medio si ottiene sommando fra loro tutti gli elementi e poi dividendo per il numero degli elementi. Il programma risolutivo Media.java non differisce molto da quello cha calcola la somma di un vettore. Infatti, occorre prima calcolare la somma degli elementi di un vettore, e poi semplicemente dividere per il numero di elementi del vettore.
/*
  Calcola la media degli elementi di un vettore.
*/

class Media {
  public static void main(String[] args) {
    int vettore[]={4, 9, 1, 3, 5};
    int i;
    double somma, media;

    somma=0;

    for(i=0; i<=vettore.length-1; i=i+1) {
      somma=somma+vettore[i];
    }

    media=somma/vettore.length;

    System.out.println("Media = " + media );
  }
}


Si noti che la variabile somma è stata dichiarata come reale, anche se il suo contenuto, essendo una somma di numeri interi, sarà sempre un numero intero. La ragione di questa scelta è legata al modo in cui vengono gestite le operazioni aritmetiche in Java. Come si è visto nella introduzione delle variabili reali, la divisione fra due numeri interi produce sempre un numero intero che è la parte intera della divisione. Per ottenere il risultato corretto, usiamo quindi una variabile reale per memorizzare la somma. Infatti, la divisione fra questa variabile reale e la lunghezza del vettore (che è intera) produce un risultato reale.

Moltiplicazione fra vettori

La moltiplicazione fra due vettori a e b si può effettuare solo se hanno lo stesso numero di elementi. Se questo numero è n, allora la somma è definita come:
Ancora una volta, si tratta di sommare fra loro un certo numero di elementi. Come al solito, usiamo una variabile per memorizzare le somme parziali, e a questa variabile assegnamo inizialmente il valore 0. Dal momento che la somma è composta da un addendo per ogni valore di i compreso fra 0 e n-1, facciamo un ciclo usando questi due estremi. Precisamente, dato che n è il numero di elementi dei due vettori, facciamo un ciclo in cui i parte da 0 e arriva a x.length-1. Ad ogni passo, calcoliamo il prodotto a[i]*b[i], e lo aggiungiamo alla somma parziale.
Il programma Moltiplicazione.java risolve questo problema.
class Moltiplicazione {
  public static void main(String[] args) {
    int x[]={15, 48, 81, 14, 47, 80, 13, 46, 79, 12, 45, 78, 11, 44, 77, 10, 43, 76, 9, 42, 75, 8, 41, 74, 7, 40, 73, 6, 39, 72, 5, 38, 71, 4, 37, 70, 3, 36, 69, 2, 35, 68, 1, 34, 67, 0, 33, 66, 99, 32, 65};
    int y[]={27, 60, 93, 26, 59, 92, 25, 58, 91, 24, 57, 90, 23, 56, 89, 22, 55, 88, 21, 54, 87, 20, 53, 86, 19, 52, 85, 18, 51, 84, 17, 50, 83, 16, 49, 82, 15, 48, 81, 14, 47, 80, 13, 46, 79, 12, 45, 78, 11, 44, 77};
    int i;
    int r;

    if( x.length != y.length ) {
      System.out.println("I due vettori hanno dimensioni diverse");
    }
    else {

      r=0;

      for(i=0; i<=x.length-1; i=i+1) {
        r=r+x[i]*y[i];
      }

      System.out.println("Il prodotto fra i due vettori vale "+r);
    }
  }
}

All'inizio del programma viene controllato che i due vettori abbiano effettivamente lo stesso numero di componenti. Se i due vettori hanno dimensioni diverse, si stampa un messaggio di errore e basta. In caso contrario (ossia i due vettori hanno la stessa dimensione), si effettua la moltiplicazione con il metodo che si è visto.

Salva valori di una funzione

Un possibile uso dei vettori è quello di memorizzare i valori che una funzione assume in un certo intervallo. Si supponga per esempio di voler stampare alcuni valori di una funzione in un certo intervallo, e poi di volere il valore medio, minimo e massimo. Il modo più semplice è quello di scrivere prima le istruzioni di stampa di una funzione, poi scrivere delle istruzioni che calcolano la media, poi quelle che calcolano il massimo, ecc.
Questo tipo di approccio ha lo svantaggio che i valori della funzione vengono calcolati una prima volta per la stampa, una seconda volta per fare la somma, ecc. Questo non è un problema per le funzioni viste fino ad ora, che sono facili da valutare per il calcolatore. D'altra parte, esistono funzioni la cui valutazione può richiedere molto tempo.
Per evitare di ripetere più volte le stessa operazioni di calcolo della funzione, è possibile memorizzare alcuni valori calcolati in un vettore, per poi poterli usare in seguito quando servono senza dover ogni volta valutare di nuovo la funzione.
Per fare questo, il primo passo è decidere quali sono i valori che potrebbero essere utili in seguito. Per esempio, assumiamo che i valori di f(x) con x intero che va da 0 a 100 saranno molto usati. Possiamo quindi calcolare questi valori una volta sola all'inizio e memorizzarli in un vettore. Dal momento che da 0 a 100 ci sono 101 numeri interi, il vettore deve avere dimensione 101. Se la funzione dà risultati reali, il tipo del vettore deve essere double:
class SalvaFunzione {
  public static void main(String[] args) {
    double[] fvett=new double[101];
La successiva operazione è quella di calcolare il valore di f(x) con x che va da 0 a 101, e memorizzare questi valori nel vettore. Per fare questo è necessaria una variabile intera x e un ciclo for.
    int x;

    /* inizializza il vettore */
    for(x=0; x<=100; x=x+1) {
      fvett[x]=x*x/2+Math.sqrt(Math.abs(x))-12;
    }
A questo punto, ogni volta che ci serve il valore di f(x), e x ha una valore intero compreso fra 0 e 100, possiamo utilizzare i valori memorizzati nel vettore. Per esempio, se vogliamo la media dei valori della funzione fra 10 e 110, calcoliamo la somma e dividiamo per il numero di punti:
    /* valore medio della funzione da 10 a 110 */
    somma=0;
    for(x=10; x<=110; x=x+1) {
      if( (x>=0) && (x<=100) ) {
        somma=somma+fvett[x];
      }
      else
        somma=somma+x*x/2+Math.sqrt(Math.abs(x))-12;
      }
    }
    System.out.println("La media fra 10 e 110 vale "+somma/101);
Queste istruzioni non differiscono da quelle di calcolo di una media. L'unica differenza è che ogni volta che si vuole il valore f(x), prima di tutto si controlla se x sta fra 0 e 100. Se ci sta, si usa il valore memorizzato nel vettore. Se non c'è, si calcola la funzione usando la sua definizione.
Il programma completo SalvaFunzione.java contiene anche la stampa dei valori della funzione fra -200 e +200, sempre cercando di usare i valori memorizzati.
/*
  Salva alcuni valori di una funzione in un vettore,
  per poterli usare di nuovo quando servono.
*/

class SalvaFunzione {
  public static void main(String[] args) {
    double[] fvett=new double[101];
    int x;
    double somma;

    /* inizializza il vettore */
    for(x=0; x<=100; x=x+1) {
      fvett[x]=x*x/2+Math.sqrt(Math.abs(x))-12;
    }

    /* valore medio della funzione da 10 a 110 */
    somma=0;
    for(x=10; x<=110; x=x+1) {
      if( (x>=0) && (x<=100) ) {
        somma=somma+fvett[x];
      }
      else {
        somma=somma+x*x/2+Math.sqrt(Math.abs(x))-12;
      }
    }
    System.out.println("La media fra 10 e 110 vale "+somma/101);

    /* stampa i valori della funzione da -200 a +200 */
    for(x=-200; x<=200; x=x+1) {
      if( (x>=0) && (x<=100) ) {
        System.out.println(fvett[x]);
      }
      else {
        System.out.println(x*x/2+Math.sqrt(Math.abs(x))-12);
      }
    }
  }
}

Moltiplicazione senza moltiplicazione

Secondo alcune fonti, i babilonesi utilizzavano una tecnica di moltiplicazione che sfruttava una tabella dei quadrati. Esistevano delle tabelle in cui si poteva trovare, per ogni numero n fino a un certo valore, il numero n2. Il vantaggio del metodo era quello di non richiedere moltiplicazioni. In particolare, si usava la formula:
xy = ( (x+y)2 - x2 -y2 )/2
Vogliamo realizzare un programma che utilizza la stessa tecnica: prima compiliamo una tabella di quadrati, e poi effettuiamo delle moltiplicazioni usando questo metodo.
Per memorizzare la tabella dei quadrati, usiamo un vettore di cento elementi. Questo vettore è sufficiente a moltiplicare due numeri la cui somma non supera 100. Una volta scritti i valori nel vettore, possiamo utilizzarli per calcolare tutte le moltiplicazioni necessare. Il programma completo MoltiplicazioneBabilonese.java è riportato qui sotto.
/*
  Moltiplicazione fra interi la cui somma e' minore
  di 100 usando il metodo babilonese.
*/

class MoltiplicazioneBabilonese {
  public static void main(String[] args) {
    int quadrati[]=new int[101];
    int i;
    int a=10, b=20, c=2, d=4, e=32, f=31;

    for(i=0; i<=100; i=i+1) {
      quadrati[i]=i*i;
    }

    System.out.println( (quadrati[a+b]-quadrati[a]-quadrati[b])/2 );
    System.out.println( (quadrati[c+d]-quadrati[c]-quadrati[d])/2 );
    System.out.println( (quadrati[e+f]-quadrati[e]-quadrati[f])/2 );
  }
}

fonte: http://www.dis.uniroma1.it/~liberato/java/Array.html

Commenti

Post popolari in questo blog

Simulazioni di reti (con Cisco Packet Tracer)

Esercizi sulla rappresentazione della virgola mobile IEEE 754 (Floating Point)