PROGRAMMARE IL MASSIMO COMUNE DIVISORE

PROGRAMMARE IL MASSIMO COMUNE DIVISORE
Cosimo Laneve
1
argomenti
1. il massimo comune divisore 2. l’algoritmo della scuola e ottimizzazioni
3. il teorema di Euclide e l’algoritmo relativo
4. ottimizzazione dell’algoritmo di Euclide
5. cenni di complessità computazionale
2
algoritmo MCD/1 – MCD della scuola
1. prendi due numeri m ed n;!
2. calcola i divisori (primi) di m e di n;!
a) calcolo dei divisori (primi) di m: si usa una sequenza di
naturali: il primo elemento sarà l’esponente di 2, il
secondo sarà l’esponente di 3, il terzo sarà l’esponente
di 4, etc.; si usa un valore k che rappresenta il
divisore (primo). All’inizio k = 2;!
i. x rappresenta l’esponente: x=0; !
ii. calcola m/k;!
!
se il resto è 0 allora m = m/k e x=x+1 e !
! riesegui ii; altrimenti metti il valore di x in coda
! alla sequenza, e vai a i. con k= k+1!
iii. quando m diventa 1 il calcolo termina!
b) fare lo stesso procedimento per n !
3. sia h1·h2·...·hs la sequenza ottenuta dal calcolo dei
divisori di m; sia h1’·h2’·...·ht’ la sequenza ottenuta dal
calcolo dei divisori di n; sia r= min(s,t)!
min(hr,hr’)
4. MCD(m,n) = 2min(h1,h1’)*3min(h2,h2’)
*...*(r+1)
3
algoritmo MCD/1 – MCD della scuola/commenti
• nel calcolo dei divisori di un numero, gli unici esponenti
non nulli corrisponderanno a divisori primi (non è
scritto ma deriva dall’algoritmo)
• le iterazioni dell’algoritmo nel caso pessimo (m ed n
sono co-primi) sono m+n+max(m,n)
• l’implementazione in C++ dell’algoritmo ha un errore…
• l’algoritmo si può migliorare iterando sino a sqrt(m)
teorema: un numero m non è primo se è divisibile per
numeri compresi tra 2 e sqrt(m) (estremi inclusi)
4
algoritmo MCD/2: un metodo più diretto per il MCD
1. prendi due numeri m ed n;!
2. prendere il più piccolo dei due numeri, sia esso m;!
3. sia mcd = 1!
4. si verifica che ogni numero x compreso tra 2 e il
numero m sia o meno un divisore dei due numeri in
input;!
5. nel caso x è un divisore, allora mcd = mcd*x e
torna a 4 aggiornando m = m/x e n = n/x; altrimenti
x = x+1 e torna a 4!
!
// l’algoritmo termina quando x > m !
!
commenti: numero di iterazioni eseguite (numeri co-primi)
!
!
≤ min(m,n)
5
algoritmo MCD/3: il Teorema di Euclide
Teorema di Euclide: se m>n allora MCD(m,n) = MCD(m-n,n)!
prova: innanzitutto si osservi che MCD(m,n) è anche un divisore di m-n:
quindi m !
n !
m-n ! = MCD(m,n)*(h-k)
= MCD(m,n)*h!
= MCD(m,n)*k!
Ora si osservi che MCD(m,n) è anche il massimo comune divisore tra m-n e n:
per assurdo assumiamo che non sia il massimo, perciò esiste h’>1 k=h’*k’ e h-k = h’*h” quindi
n !
!
= !
MCD(m,n)*h’*k’!
! m-n!
! = !
MCD(m,n)*h’*h”!
! (m-n)+n ! = !
MCD(m,n)*h’*(h”+k’)
assurdo!
6
algoritmo MCD/3: l’algoritmo di Euclide
1. se !
m == n !
allora !
m = mcd(m,n) !
2. se !
(m != n) ! allora !
!
i.
m > n allora m = m - n (perchè mcd(m,n) = mcd(m-n,n))!
!
ii.
m < n
allora n = n - m (perchè mcd(m,n) = mcd(m,n-m))!
!
iii. ritorna a 1.!
3. stampa m
commenti: numero di iterazioni eseguite (caso pessimo uno dei due valori è 1)
≈ max(m,n)
7
algoritmo MCD/4: l’algoritmo di Euclide ottimizzato
osservazione: quando uno dei due numeri è molto più grande
dell’altro, allora l’algoritmo di Euclide esegue numerosi cicli per sottrarre
la quantità più piccola dal numero più grande
esempio. m = 1000,
1o iterazione: 2o iterazione: 3o iterazione: 499o iterazione: n = 2
m =
m =
m =
. . .
m =
1000, ! n = 2
998, ! n = 2
996, ! n = 2
2,
!
n = 2
!
soluzione più efficiente: utilizzare il resto invece della differenza!
esempio:
m = 1000, n = 2
1o iterazione: m = 1000, n = 2
2o iterazione: m = 2 (perchè 1000%n == 0),
8
n = 2
b
1. se n>m allora r = n altrimenti r = m; m = n ; n = r ;!
2. se !
a)
b)
c)
d)
(r != 0) ! allora!
r = m % n ;!
m = n ; !
n = r ;!
ritorna a 2!
3.!stampa m
! !
commenti: numero di iterazioni eseguite (caso pessimo) ≈
log2(max(m,n))
perchè m % n <= m/2
9