Pari o dispari?

Come si stabilisce se un numero è pari o dispari?

In matematica, qualsiasi numero intero è o pari o dispari. Se è un multiplo di due, è un numero pari, altrimenti, è un numero dispari. Esempi di numero pari sono: -4, 0, 8 e 70. Esempi di numero dispari sono -5, 1 e 71. (fonte Wikipedia)

La teoria ci insegna quindi che se un numero intero è divisibile per 2 allora è pari, altrimenti è dispari.

Come si fa a vedere se un numero è divisibile per 2? La risposta è: dividiamo il numero per 2, se dà resto 0 allora il numero è divisibile per due.

Questa operazione molto semplice, nasconde qualche sorpresina che vale la pena discutere.

Consideriamo l’operazione aritmetica della divisione. Essa può essere rappresentata in questo modo:

Se N è il numero incriminato che dobbiamo dividere per 2 allora

R=N-(Q*2)

dove R è il resto della divisione di N per 2 e Q il quoziente

Esempio:

per N=23

N diviso 2 fa 11 con  il resto di 1.

Cioè Q=11 e quindi R=23-(11*2)=23-22=1

Quindi N è dispari

 

In Java:

 

int n=23; /* IL NUMERO DA CONTROLLARE */

        /* LA TEORIA DICE CHE IL RESTO DELLA DIVISIONE PER DUE DEVE ESSERE 0 PER I NUMERI PARI */

        /* PRIMA SOLUZIONE */

System.out.println("PRIMA SOLUZIONE");

        int quoziente=n/2; /* divisione intera */

        int resto1=n-quoziente*2;

        if(resto1==0) {
            System.out.println(n +" E' NUMERO PARI");
        } else {
            System.out.println(n +" E' NUMERO DISPARI");
        }

NB:

Ora se guardiamo l’operazione:

int quoziente=n/2;

poichè n è intero e quoziente s’aspetta un intero,  l’operazione di divisione “/” viene calcolata come un’operazione intera (senza virgola per capirci).

Ovviamente questa soluzione in termini di tempo risulta essere la più dispendiosa possibile. Molti di voi avranno già pensato: “Perché non usare l’operatore modulo % ?”

Beh si e quindi ecco la seconda versione:

 

 

        /* SECONDA SOLUZIONE */
System.out.println("SECONDA SOLUZIONE");

        int resto2= n % 2;

        if(resto2==0) {
            System.out.println(n +" E' NUMERO PARI");
        } else {
            System.out.println(n +" E' NUMERO DISPARI");
        }

 

Qualcuno più sveglio però saprà anche che se pensiamo alla rappresentazione in binario dei numeri interi questi hanno una caratteristica ancor più simpatica:

il bit con peso 2 elevato a 0 compare una volta 0 ed una volta 1.

Esempio rappresentiamo i primi 8 numeri da 1 a 8 in binario (su 4 bits)

0001
0010
0011
0100
0101
0110
0111
1000

Noterete che la cifre in grassetto si alternano in un balletto di zero e uno.

A questo punto ci viene in soccorso l’operatore logico AND che nello specifico si rappresenta con &

In pratica se ad un numero applichiamo l’operazione “N and 1” (in Java: n & 1) in pratica stiamo verificando se l’ultimo bit (il primo se guardiamo da destra) è 0 oppure 1, basandoci sulla legge che

se a e b sono due bit

a & b == 1 se e solo se a==1 e b==1

Per cui la nostra terza soluzione:

 

 

        /* TERZA SOLUZIONE */
System.out.println("TERZA SOLUZIONE");

        int resto3= n & 1;

        if(resto3==0) {
            System.out.println(n +" E' NUMERO PARI");
        } else {
            System.out.println(n +" E' NUMERO DISPARI");
        }

 

Vi chiederete: “Un post per calcolare se un numero è pari o dispari? Ci stai offendendo?”

No in realtà mi è capitato in molti anni di formazione di programmazione di base, di trovarmi in situazioni in cui un allievo tramite questo banale esempio ha capito che:

1. non c’è solo una soluzione ai problemi computazionali
2. la scelta di una soluzione rispetto ad un’altra dipende sempre dal contesto: (esempio: se dobbiamo controllare non un solo numero, ma un insieme di numeri con una cardinalità pari ad un miliardo, quale soluzione finisce prima la uno, la due o la tre ?)

Grazie per l’attenzione.