Indice    Avanti    Indietro




8. Procedure di tipo aritmetico
       Istruzioni esaminate: for, ct, print, remainder, if, stop


Sarebbe un errore pensare che il raggio d'azione del Logo sia limitato alla costruzione di figure. L'MswLogo è un linguaggio di programmazione completo che ci consente di realizzare procedure di qualsiasi tipo. In questo numero ne vedremo alcune di tipo aritmetico.

La prima che esamineremo ha lo scopo di visualizzare i numeri da 1 a 10:

to conta
   for [i 1 10][print :i]
end

Prima di spiegarne il funzionamento, vediamone l'effetto. A tal fine ridimensioniamo (ingrandiamo) la finestra commander trascinando in modo opportuno, col mouse, i suoi bordi (come facciamo per qualsiasi finestra di Windows). Diamo poi in modo diretto l'istruzione ct (clear text, pulisci testo) che cancella tutto il testo che fosse presente nella finestra commander. Digitiamo infine conta. Ecco quello che vedremo.



Nella procedura troviamo due nuove istruzioni. L'istruzione print (stampa) serve a visualizzare dati nella finestra commander. Nel nostro caso servirà a visualizzare il valore assegnato alla variabile i.

L'istruzione for ha lo scopo di ripetere un blocco di istruzioni facendo variare una variabile di controllo tra due estremi. Nel nostro caso la variabile di controllo è la variabile i che assume valori interi da 1 a 10 (1 e 10 sono i due estremi). Il blocco di istruzioni da ripetere, racchiuso tra la seconda coppia di parentesi quadre, è nel nostro caso ridotto all'unica istruzione print :i.

Cerchiamo di capire come funziona il "ciclo for". All'inizio viene assegnato alla variabile i il valore 1 e viene eseguito per la prima volta il blocco di istruzioni, nel nostro caso la sola istruzione print :i; poiché il valore di i è 1 viene visualizzato il numero 1. Dopo questo primo passo viene incrementata di una unità la variabile di controllo i e le viene quindi assegnato il valore 2; viene eseguito per la seconda volta il blocco, ma ora l'istruzione print :i visualizzerà il numero 2 perché questo è l'attuale valore della variabile. Il processo continua così finché non si arriva ad assegnare ad i il valore 10, che è l'estremo finale del ciclo. E' quindi chiaro che saranno visualizzati i numeri da 1 a 10. Il blocco viene ripetuto 10 volte ma, deve essere chiaro, con diversi valori di i.

Ecco una piccola variazione della procedura precedente

to conta :m :n
   for [i :m :n][print :i]
end

Dovrebbe esservi chiaro che digitando in modo diretto conta 3 7 saranno visualizzati i numeri 3, 4, 5, 6, 7, mentre digitando conta -1 0 saranno visualizzati i numeri -1, 0.

La procedura di cui ci occuperemo ora è più interessante e serve a determinare i divisori di un numero dato. Prima di affrontarla è però opportuno esaminare un importante comando di tipo aritmetico, il comando remainder (resto), che ci farà comodo in molte situazioni. Il comando remainder ha in input (cioè in entrata) due parametri, i numeri interi m e n, e ci fornisce in output (cioè in uscita) il resto della divisione di m per n. Provate ad esempio a dare in modo diretto il comando

print remainder 10 3

L'output visualizzato sarà 1 (perché il resto della divisione di 10 per 3 è proprio 1).

Ed ecco la procedura per determinare i divisori del numero n

to divisori :n
   for [i 1 :n][ if (remainder :n :i) = 0 [print :i] ]
end

Esaminiamo la procedura. Il numero di cui si vogliono trovare i divisori è n. Nell'istruzione for la variabile di controllo i varia da 1 a n. Il blocco da ripetere è costituito dall'unica istruzione

if (remainder :n :i) = 0 [print :i]

Si tratta della nuova istruzione if (se), di fondamentale importanza. Traduciamone a parole il significato:

SE il resto della divisione di n per i è 0 ALLORA visualizza i
o, equivalentemente,
SE i è un divisore di n ALLORA visualizza i

Ora attenzione, poiché l'istruzione if è interna a un ciclo for, saranno visualizzati quei valori di i, tra 1 e n, che sono divisori di n. Proprio quel che volevamo. Deve esservi chiaro che l'istruzione if sarà eseguita n volte, con i che varia da 1 a n.

Mettiamo in esecuzione la nostra procedura. Digitiamo nel campo di input della finestra commander divisori 12 e poi divisori 11. Ecco quel che vedremo.



Qualcuno si sarà forse reso conto che la procedura divisori non è troppo efficiente (nel senso che vengono "testati" dei valori di i che a priori possiamo scartare). E' sufficiente far variare i tra 1 e n/2; l'unico divisore di n maggiore di n/2 è infatti n. Possiamo allora modificare la nostra procedura in questo modo

to divisori :n
   for [i 1 :n/2][ if (remainder :n :i) = 0 [print :i] ]
   print :n
end

Tenete presente che se n fosse dispari, ad esempio 7, la variabile di controllo avrebbe come estremo superiore la parte intera di n/2 cioè 3.

Ecco un'ultima procedura, un po' più impegnativa, per decidere se un numero n è primo oppure no

to primo? :n
   if :n = 2 [ print [è primo] stop ]
   for [i 2 :n/2] [ if (remainder :n :i) = 0 [print [non è primo] stop] ]    print [è primo]
end

Attenzione alla terza riga: le parentesi rosse individuano il blocco del comando for, quelle azzurre il blocco del comando if; quest'ultimo blocco contiene le due istruzioni print [non è primo] e stop che saranno eseguite solo se la condizione è verificata cioè solo se i è un divisore di n maggiore o uguale a 2. Tenete presente che l'istruzione stop ha lo scopo di interrompere immediatamente l'esecuzione della procedura. L'istruzione stop gioca qui un ruolo essenziale: provate a toglierla in uno dei due punti in cui compare e riflettete su quel che succede. E' importante capire che l'ultimo comando della procedura, print [è primo], sarà eseguito nel solo caso in cui tutti i test del ciclo for diano esito negativo (cioè se non è stato trovato alcun divisore di n). Notate inoltre che l'istruzione print visualizza, in questo caso, il testo contenuto tra parentesi quadre.

Anche questa procedura può essere resa più efficiente riducendo il numero dei test. Sapete dire in che modo?