Soluzione Esercizio 7 dell'Esercitazione #2

Esercizio 7

Obiettivo: Familiarizzare con il tipo di dato boolean.

Attività:

  1. Il tipo boolean è il più semplice di tutti, dato che le variabili di quel tipo possono assumere solo i valori true e false. Eppure spesso risulta di difficile comprensione ai neofiti. Scrivete l'istruzione di assegnamento che assegna alla variabile booleana p il valore true se la variabile intera x è pari, false altrimenti. Scrivete un breve programma per verificare che la vostra soluzione è corretta. Suggerimento: ripensate all'esercizio precedente e usate l'operatore di uguaglianza "==" nella parte destra dell'assegnamento. Fate attenzione: la modifica è minima, ma richiede un salto logico...
  2. Scrivete l'istruzione di assegnamento che assegna alla variabile booleana p il valore true se la variabile intera x ha un valore positivo (maggiore o uguale a zero), false altrimenti. Scrivete un breve programma per verificare che la vostra soluzione è corretta. Suggerimento: Questo esercizio e quelli immediatamente successivi sono varianti minime del precedente.
  3. Scrivete l'istruzione di assegnamento che assegna alla variabile booleana p il valore true se la variabile intera x ha un valore positivo (maggiore o uguale a zero) o pari, false altrimenti. Scrivete un breve programma per verificare che la vostra soluzione è corretta. Suggerimento: usate gli operatori logici.
  4. Scrivete l'istruzione di assegnamento che assegna alla variabile booleana p il valore true se la variabile intera x ha un valore positivo (maggiore o uguale a zero) e pari, false altrimenti. Scrivete un breve programma per verificare che la vostra soluzione è corretta.
  5. Scrivete l'istruzione di assegnamento che assegna alla variabile booleana p il valore true se la variabile intera x ha un valore positivo compreso in uno dei seguenti intervalli: [15,18], [39,45], [91,103], false altrimenti. Scrivete un breve programma per verificare che la vostra soluzione è corretta.

Soluzione

  1. Quello che ci serve è un'espressione che assuma un valore booleano (quindi true o false) a seconda che x sia pari o dispari. Abbiamo visto nell'esercizio precedente che l'espressione x % 2 vale zero se x è pari, uno se x è dispari, e questi sono gli unici due valori possibili. Ma allora basta trovare il modo di ottenere true se una certa espressione (nel nostro caso x % 2) è uguale a zero e false se quell'espressione è uguale a uno. E questo si può fare con l'operatore ==, da usare per chiedersi se la nostra espressione è zero. L'espressione che ci serve è quindi (x % 2) == 0.
    Quindi l'istruzione di assegnamento cercata è: p = ((x % 2) == 0) (in realtà, le parentesi sono tutte non necessarie perché la priorità dell'operatore di modulo % è superiore a quella dell'operatore di confronto == la quale è a sua volta superiore a quella dell'operatore di assegnamento =) e il programma per verificare la risposta è:
    class PariDispariBoolean {
      public static void main(String[] args) {
        boolean p;
        int x;
        x = 17;
        p = x % 2 == 0;
        System.out.println(p);
      }
    }
    
    Compilando ed eseguendo si ottiene:
    >javac PariDispariBoolean.java
    >java PariDispariBoolean
    false
    
    Vediamo alcune soluzioni alternative ma peggiori. Prima di leggere la soluzione corretta, alcuni di voi avranno pensato, ad esempio, a:
        p = (x % 2 == 0) == true;
    
    Questa istruzione ottiene l'effetto voluto, ma è peggiore di quella proposta. Qui l'errore consiste nel confrontare un valore booleano con true (ma sarebbe lo stesso con false). Questo va sempre evitato! E questo errore è anche semplice da evitare: basta sostituire sistematicamente nei vostri programmi
        E == true
    
    con
        E
    
    e
        E == false
    
    con
        !E
    
    (not E).
    Altri di voi avranno pensato che per assegnare a p il valore cercato bisognasse usare l'operatore condizionale "?:":
        p = (x % 2 == 0) ? true : false;
    
    Anche questa istruzione ottiene l'effetto voluto ma, rispetto alla soluzione migliore, è meno elegante e meno efficiente. Un programmatore professionista non farebbe mai così. In realtà, anche questo errore è semplice da evitare: basta verificare che nei vostri programmi non compaia mai un'espressione del tipo
         E ? true : false
    
    dove, al posto di E c'è un'espressione booleana qualsiasi. Se l'espressione precedente compare nel vostro programma, affrettatevi a sostituirla con
         E
    
    prima che il prof. se ne accorga...
    Se poi avete addirittura scritto
        p = (x % 2 == 0) == true ? true : false;
    
    allora siete riusciti a commettere entrambi gli errori precedenti...
  2. Qui l'espressione cercata è molto simile a quella dell'esercizio precedente. Invece di verificare se il modulo della divisione per 2 è zero, bisogna semplicemente verificare se x è maggiore di (o uguale a) zero, ossia: x >= 0. Quindi l'istruzione cercata è p = (x >= 0) (le parentesi sono superflue) e il programma (da compilare ed eseguire per più valori di x) è:
    class Positivo {
      public static void main(String[] args) {
        boolean p;
        int x;
        x = -12;
        p = x >= 0;
        System.out.println(p);
      }
    }
    
    Compilando ed eseguendo si ottiene:
    >javac Positivo.java
    >java Positivo
    false
    
  3. Il valore da assegnare a p è ottenuto come or logico delle espressioni trovate nei due esercizi precedenti: x >= 0 per capire se x è positivo e x % 2 == 0 per capire se x è pari. La risposta è quindi p = (x >= 0) || (x % 2 == 0). Le parentesi non sono indispensabili, ma in questo caso aiutano perché l'espressione comincia a essere meno banale delle precedenti. Il programma per verificare la correttezza della nostra risposta è:
    class PositivoOPari {
      public static void main(String[] args) {
        boolean p;
        int x;
        x = -12;
        p = (x >= 0) || (x % 2 == 0);
        System.out.println(p);
      }
    }
    
    e la sua esecuzione (dopo, ovviamente, la compilazione) è:
    >java PositivoOPari
    true
    
    Invece dell'operatore "||" si sarebbe potuto usare l'altro operatore di or logico "|", e il risultato sarebbe stato lo stesso. La prima soluzione è leggermente preferibile per questioni di efficienza, in quanto risparmiamo all'interprete Java la fatica (minima, in verità...) di valutare l'espressione x % 2 == 0 quando l'espressione (x >= 0) è true.
    Le soluzioni che usano l'operatore condizionale "?:" per costruire espressioni più o meno complesse per ottenere lo stesso risultato sono, analogamente a prima, meno eleganti ed efficienti.
  4. Leggendo attentamente il testo dell'esercizio, si nota che l'unica differenza dall'esercizio precedente è la congiunzione "e" al posto della "o". La risposta sarà quindi molto simile alla precedente: p = (x >= 0) && (x % 2 == 0). E anche il programma non è molto diverso:
    class PositivoEPari {
      public static void main(String[] args) {
        boolean p;
        int x;
        x = -12;
        p = (x >= 0) && (x % 2 == 0);
        System.out.println(p);
      }
    }
    
    E l'esecuzione dà:
    >java PositivoEPari
    false
    
    Anche qui, l'uso di "&&" invece di "&" è leggermente preferibile.
  5. Dobbiamo scrivere un'espressione booleana vera (cioè un'espressione che viene valutata a true) nel caso in cui x appartenga a uno dei tre intervalli. Incominciamo dal vedere come controllare se una variabile ha un valore compreso in un intervallo; per fissare le idee, lavoriamo su x e sul primo intervallo di questo esercizio, [15,18].
    La sintassi Java non ci consente di scrivere espressioni come 15 <= x <= 18 o 18 >= x >= 15. Questo può sembrare strano, in quanto sappiamo di poter scrivere cose come x + y + z (dove x, y e z sono, ad esempio, di tipo int). Ma i due casi sono diversi: vediamo di capire perché. Quando scriviamo x + y + z in realtà intendiamo (usando la proprietà associativa della somma) (x + y) + z. Infatti l'interprete Java esegue prima la somma x + y e ne memorizza il risultato in una variabile temporanea il cui valore viene poi sommato a z per ottenere il risultato dell'espressione. Notiamo che la variabile temporanea è di tipo int, e quindi la seconda operazione di somma è una normalissima somma fra due tipi int.
    Diverso è il caso di 15 <= x <= 18. Se infatti, analogamente a quanto appena fatto per x + y + z, riscriviamo questa espressione come (15 <= x) <= 18 vediamo subito che c'è qualcosa di strano. Infatti, il primo confronto 15 <= x è un normale confronto fra due valori di tipo int e restituisce un valore di tipo boolean. Ma il secondo confronto sarebbe un confronto fra un valore di tipo boolean (il risultato del primo confronto) e un int! E questo porta a un errore in compilazione.
    Quindi, per sapere se x è nell'intervallo [15,18], quello che dobbiamo invece fare è costruire un'espressione vera (che assume il valore true) se e solo se x è maggiore o uguale di 15 e x è minore o uguale di 18. Si tratta quindi di usare nuovamente l'operatore di and logico: x >= 15 && x <= 18.
    Questo per il primo dei tre intervalli. Per gli altri due si procede in modo analogo, ottenendo: x >= 39 && x <= 45 e x >= 91 && x <= 103. Ora resta da capire come mettere insieme le tre espressioni trovate in un'unica espressione il cui valore va assegnato a p. L'espressione risultante deve essere vera (true) se e solo se x è in uno qualsiasi dei tre intervalli, ossia nel primo o nel secondo o nel terzo. Si usa l'operatore di or logico, e l'espressione risultante è (x >= 15 && x <= 18) || (x >= 39 && x <= 45) || (x >= 91 && x <= 103) Il programma è:
    class Guerre {
      public static void main(String[] args) {
        boolean p;
        int x;
        x = 94;
        p = (x >= 15 && x <= 18) || 
            (x >= 39 && x <= 45) || 
            (x >= 91 && x <= 103);
        System.out.println(p);
      }
    }
    
    E la sua esecuzione è:
    >java Guerre
    true
    
    Anche qui le parentesi non sono necessarie (perché l'and logico ha precedenza sull'or) ma aiutano la comprensione, così come la scrittura dell'espressione su più righe. L'uso di l'uso di "&&" invece di "&" e di "||" invece di "|" è leggermente preferibile per i soliti motivi (in realtà, capita piuttosto raramente di dover usare gli operatori "&" e "|").

Fate l'amore e non la guerra! Valid HTML 4.01! Valid CSS! Stefano Mizzaro
Last modified: 2003-03-11