Massimo Comune Divisore: dati due numeri a e b, calcolare MCD(a,b)

Il file MCD.TXT contiene due numeri di esempio, abbastanza grandi da 
valutare la differenza fra algoritmi differenti. Ancora una volta, 
MCD0.C  uno scheletro vuoto per provare a realizzare la propria soluzione.
  

1) Algoritmo esaustivo: scorre interamente l'insieme dei possibili divisori
  verificando ogni volta se il numero corrente  divisore di entrambi i 
  termini. Conserva il massimo valore trovato che soddisfa tale condizione.
  
  L'insieme dei possibili divisori va da 1 (sicuramente divisore comune)
  al pi piccolo dei due termini, min(a,b).
  
  Se li scorriamo per valori crescenti, dobbiamo conservare l'ultimo numero
  che sia divisore di entrambi.
  Se li scorriamo per valori decrescenti, dobbiamo conservare il primo. 
  In realt, possiamo anche fermarci al primo, dato che altri divisori non 
  servono.
  
  Quindi, partendo dal basso dobbiamo comunque arrivare fino a min(a,b),
  partendo dall'alto possiamo fermarci prima di arrivare a 1: 
  partiremo dall'alto.
  
  min = ( (a < b) ? a : b);
  for (MCD = min; MCD > 1; MCD--)
    if ( (a % MCD == 0) && (b % MCD == 0) )
      break;

  return MCD;

  Si pu osservare che un divisore comune esiste sicuramente (ed  1) e che 
  si esce dal ciclo sempre dopo averlo trovato, per cui la condizione di 
  uscita pu essere semplificata:

    min = ( (a < b) ? a : b);
    for (MCD = min; (a % MCD != 0) || (b % MCD != 0); MCD--);

    return MCD;

  Questa versione  pi compatta e forse elegante, ma un ciclo con 
  istruzione vuota non  il massimo della chiarezza:  importante tenere 
  "return MCD" ben separato dal ciclo, per sottolineare che non ne  parte.
  
1b) Volendo migliorare ulteriormente, si pu osservare che, tolti a e b, 
  i divisori tendono ad addensarsi su valori "piccoli": a/2, a/3, ecc...
  Si pu quindi testare a parte l'ipotesi che MCD(a,b) sia uguale ad a o b
  (ovviamente al minimo fra i due), e partire con lo scorrimento da 
  min(a,b)/2.

2) Algoritmo basato sulla fattorizzazione: determina l'insieme dei fattori 
  di uno e dell'altro termine e la loro molteplicit. Dopo di che, 
  costruisce il minimo comune divisore includendo tutti i fattori comuni 
  con la molteplicit minima fra le due.
  
  Per rappresentare l'insieme dei fattori con le loro molteplicit, usa un 
  vettore di interi, che associa ad ogni numero la sua molteplicit.
  
  Si noti come la procedura Fattorizza sfrutti il passaggio dei parametri 
  per valore: ogni volta che trova un fattore, divide il numero corrente 
  per il fattore stesso, in modo da non doverlo pi considerare. Al termine 
  della procedura, il numero corrente non risulta modificato.
  
  Il problema  la dimensione dei vettori da allocare. Se dividiamo per 10 
  i numeri dell'esempio, si riesce ad affrontare il problema, ma ci si 
  mette di pi che con la versione lenta.
  
3) Algoritmo di Euclide ricorsivo:
  Si basa sull'osservazione che il MCD di due numeri diversi tra loro 
  coincide con il MCD del numero pi piccolo e della differenza 
  (dimostrazione banale per assurdo).
  
  L'esecuzione  rapidissima, ma l'algoritmo ha un difetto: alloca sullo 
  stack un ambiente per ogni chiamata della funzione ricorsiva, cio 
  potenzialmente migliaia di ambienti.

3b) Algoritmo di Euclide iterativo:
  E' lo stesso algoritmo, ma usa un ciclo e la propriet che ad ogni 
  iterazione i due numeri correnti diminuiscono, ma conservano lo stesso 
  MCD. In questo modo evita l'occupazione (potenzialmente esplosiva) dello 
  stack.
  
  Tutti gli algoritmi iterativi sono corretti quando modificano i dati in 
  modo da avvicinarsi a una situazione finale, ma al tempo stesso 
  mantengono vera qualche propriet, in modo che combinando la propriet 
  conservata con la riduzione dei dati si possa garantire di aver costruito 
  la soluzione. In questo caso, i due numeri calano (uno dei due cala) 
  conservando il loro MCD. Quando i due numeri sono uguali, il loro MCD  
  ovvio, ed  uguale a quello dei due numeri iniziali.
  
Si pu accelerare l'algoritmo di Euclide sostituendo la differenza fra i 
due numeri con il resto della divisione del maggiore per il minore (che  
in effetti il risultato di una sequenza di differenze):  dati 21 e 91, 
anzich usare 21 e 91-21 = 70, si usano 21 e 91 % 21 = 91 - 4*21 = 7, 
eseguendo 4 differenze in una volta. Ovviamente, tutto dipende dalla 
velocit dell'operatore "%" rispetto all'operatore "-".
