Capitolo 13
Argomento: approssimazione probabilistica di pi greco

Livello: Avanzato

Nota: Alcune nozioni matematiche elementari sono necessarie per questo capitolo.

13.1 MCD (Massimo Comune Divisore)

Il MCD di due numeri interi è l’intero più grande che divide entrambi i numeri senza resto. Per esempio il MCD di 42 e 28 è 14, il MCD di 25 e 55 è 5, il MCD di 42 e 23 è 1.

Gli interi a e b si dicono coprimi o primi tra loro se non hanno un fattore comune eccetto 1 o, in modo equivalente, se il loro MCD è 1. Negli esempi precedenti 42 e 23 sono coprimi.

13.2 L’algoritmo di Euclide

L’algoritmo di Euclide calcola il MCD di due interi in modo efficiente (non dimostriamo qui che questo algoritmo è valido).

13.2.1 Descrizione dell’algoritmo

Dati due interi positivi a e b, controlliamo prima di tutto se b sia uguale a 0. Se è questo il caso allora il MCD è a. In caso contrario calcoliamo r come resto della divisione di a per b. Quindi sostituiamo a con b e b con r e ricominciamo l’algoritmo.
Per esempio calcoliamo il MCD di 2160 e 888 con l’algoritmo di Euclide:

a
b
r
2160
888
384
888
384
120
384
120
24
120
24
0
24
0

Quindi il MCD di 2160 e 888 è 24. Non c’è intero più grande che divide entrambi i numeri (infatti 2160 = 24 × 90 e 888 = 24 × 37)
Il MCD è resto più grande non uguale a 0.

13.3 Calcolare il MCD in LOGO

Una semplice procedure ricorsiva calcolerà il MCD di due interi :a e :b:

Per MCD :a :b 
  Se (modulo :a :b)=0 [output :b][output MCD :b modulo :a :b] 
Fine

Invochiamo la procedure come Print MCD 2160 888 e otterremo il risultato 24.
Nota: è importante porre tra parentesi tonde modulo :a :b altrimenti l’interprete tenterà di verificare la condizione :b = 0. Se non vuoi usare le parentesi scrivi Se 0=resto :a :b.

13.4 Calcolare l’approssimazione di pi greco

Nei fatti un famoso risultato nella teoria dei numeri dice che la probabilità di due interi scelti a caso di essere coprimi è 6
-2-
π 0,6079. Per verificare questo risultato possiamo:

Per test 
  # impostiamo la variabile contatore a 0 
  AssegnaVar "counter 0 
  Ripeti 1000 [ 
    Se (MCD Casuale 1000000 Casuale 1000000)=1 [AssegnaVar "counter :counter+1] 
  ] 
  Stampa [frequenza:] 
  Stampa :counter/1000 
Fine

Come prima nota le parentesi attorno MCD Casuale 1000000 Casuale 1000000. Se non ci fossero l’interprete cercherebbe di verificare la condizione 1 000 000 = 1. La stessa espressione si può anche scrivere come: Se 1=MCD Casuale 1000000 Casuale 1000000.

Invochiamo la procedura con test e con un po’ di pazienza otterremo frequenze che si avvicinano al valore teorico di 0,6097:

test  
0.609  
test  
0.626  
test  
0.597

La frequenza teorica è una approssimazione di 6
π2-.

Quindi, se denotiamo con f la frequenza abbiamo: f -6-
π2 da cui π2 6-
f e π ∘  --
   6-
   f.

Aggiungo al mio programma una riga che fornisca questa approssimazione di pi greco nella procedura test:

Per test 
  # impostiamo la variabile contatore a 0 
  AssegnaVar "counter 0 
  Ripeti 1000 [ 
    Se (MCD Casuale 1000000 Casuale 1000000)=1 [AssegnaVar "counter :counter+1] 
  ] 
  # Calcoliamo la frequenza 
  Assegna "f :counter/1000 
  # stampiamo lapprossimazione di pi greco 
  Stampa frase [ approssimazione di pi greco:] RadQ (6/:f) 
Fine

Invochiamo la procedura con test e con un po’ di pazienza otterremo valori di pi greco che si avvicinano a quello teorico:

test  
approssimazione di pi greco: 3.1033560252704917  
test  
approssimazione di pi greco: 3.1835726998350666  
test  
approssimazione di pi greco: 3.146583877637763

Ora voglio modificare il programma perché vorrei impostare liberamente il numero di prove. Vorrei provare con 10000 e forse con ancor più prove.

Per test :prove 
  # impostiamo la variabile contatore a 0 
  AssegnaVar "counter 0 
  Ripeti :prove [ 
    Se (MCD Casuale 1000000 Casuale 1000000)=1 [AssegnaVar "counter :counter+1] 
  ] 
  # Calcoliamo la frequenza 
  Assegna "f :counter/:prove 
  # stampiamo lapprossimazione di pi greco 
  Stampa frase [ approssimazione di pi greco:] RadQ (6/:f) 
Fine

Invochiamo la procedura così:

test 10000  
approssimazione di pi greco: 3.1426968052735447  
test 10000  
approssimazione di pi greco: 3.1478827771265787  
test 10000  
approssimazione di pi greco: 3.146583877637763

Interessante, no?

13.5 La generazione del pi greco mediante il pi greco…

Che cos’è un intero casuale? Può un intero scelto casualmente tra 1 e 1000000 essere realmente rappresentativo di tutti gli interi scelti casualmente? Osserviamo che il nostro esperimento è solo una approssimazione del modello ideale. Adesso modificheremo il metodo per generare numeri casuali…. Non useremo la primitiva Casuale ma genereremo numeri casuali usando la sequenza delle cifre del pi greco.
Le cifre del pi greco hanno sempre interessato i matematici:

In realtà sembra che la sequenza del pi greco sia veramente casuale (ancora non dimostrato). Non è possibile prevedere la cifra successiva in base alle precedenti, non c’è periodicità.
Useremo la sequenza delle cifre del pi greco per generare interi casuali:

Creiamo ora una nuova procedura chiamata CasualePi e modifichiamo la procedura test.

Per MCD :a :b 
  Se (modulo :a :b)=0 [output :b][output MCD :b modulo :a :b] 
Fine 
 
per test :prove 
  # apriamo un flusso con id 1 verso il file  millionpi.txt 
  # che deve essere nella cartella attuale 
  # altrimenti usare CambiaDirectory 
  ApriFlusso 1 "millionpi.txt 
  # assegna la variabile line per la prima linea del file millionpi.text 
  AssegnaVar "line Primo LeggiLineaDalFlusso 1 
  # impostiamo la variabile contatore a 0 
  AssegnaVar "counter 0 
  Ripeti :prove [ 
    Se 1=gcd CasualePi 7 CasualePi 7 [AssegnaVar "counter :counter+1] 
  ] 
  # Calcoliamo la frequenza 
  Assegna "f :counter/:prove 
  # stampiamo lapprossimazione di pi greco 
  Stampa frase [ approssimazione di pi greco:] RadQ (6/:f) 
  ChiudiFlusso 1 
fine 
 
per CasualePi :n 
  AssegnaVarLocale "number " 
  Ripeti :n [ 
  Se 0=count :line [AssegnaVar "line Primo LeggiLineaDalFlusso 1] 
  # imposta la variabile char al primo carattere della linea 
  AssegnaVar "char Primo :line 
  # quindi rimuove il primo carattere dalla linea 
  AssegnaVar "line EccettoPrimo :line 
  AssegnaVar "number Parola :number :char 
  ] 
  Output :number 
fine

Invochiamo la procedura come al solito:

test 10  
approssimazione di pi greco: 3.4641016151377544  
test 100  
approssimazione di pi greco: 3.1108550841912757  
test 1000  
approssimazione di pi greco: 3.081180112566604  
test 10000  
approssimazione di pi greco: 3.1403714651066386  
test 70000  
approssimazione di pi greco: 3.1361767950325627

Stiamo trovato la corretta approssimazione di pi greco utilizzando le sue stesse cifre.
E’ ancora possibile migliorare il programma calcolando il tempo del calcolo. Aggiungiamo alla prima linea della procedura text:
AssegnaVar inizio SecondiDaAvvio

Quindi aggiungiamo prima di chiudere il flusso:
Stampa Frase [Tempo impiegato: ] SecondiDaAvvio - :inizio