Upload
ravenna-poggi
View
219
Download
0
Embed Size (px)
Citation preview
AN FI 98-99 Iterazione&Invarianti
Il ragionamento iterativo
Gli invarianti di ciclo
AN FI 98-99 Iterazione&Invarianti
Impostazione di soluzioni iterative si parte dall’idea che la soluzione possa essere
ottenuta in un numero finito di n passi computazionali; si inizializza una variabile (detta accumulatore) con il
valore della soluzione “al passo iniziale” si imposta un ragionamento del tipo: “sapendo che al
passo generico i l’accumulatore esprime il valore corrente della soluzione, la soluzione al passo i+1 si ottiene modificando l’accumulatore come segue ….”.
Se il passo i rappresenta il passo finale, allora il valore della soluzione coincide con il valore dell’accumulatore.
AN FI 98-99 Iterazione&Invarianti
Il calcolo di bk
double power(double b, int k ){
return (k==0) ? 1
: //k>0
b * power(b,k-1);
}
AN FI 98-99 Iterazione&Invarianti
bk : progetto iterativo
si inizializza un accumulatore v al valore b, inteso come il valore di bi al passo i=1;
sapendo che al passo generico i (i<k) v esprime il valore corrente bi della soluzione, la soluzione al passo i+1 si ottiene modificando l’accumulatore in v*b. Se i=k, allora la soluzione e’ v.
AN FI 98-99 Iterazione&Invarianti
bk : versione iterativa
double power( double b, int k ){
return (k==0) ? 1 : powerIt(b,k,b,1);}
double powerIt( double b,int k,
double v, int i ){
return (i==k) ? v :
powerIt(b, k, v*b, i+1); }
AN FI 98-99 Iterazione&Invarianti
Invarianti di ciclo
una relazione sempre vera (ad ogni iterazione)
bk =v*bk-i
inizialmente v=b, i=1
AN FI 98-99 Iterazione&Invarianti
bk : l’invariante
double powerIt( double b, int k, double v, int i ){ return (i==k) ? // bk =v*bk-i and i=k => bk =v v : // bk =v* bk-i and i<k // bk =v* b * bk-(i+1) and i<k
// Ponendo v = v*b, i=i+1 // si riottiene bk =v* bk-i
powerIt(b, k, v*b, i+1);}
AN FI 98-99 Iterazione&Invarianti
Progettare per invarianti bk
bk = vk con v=b Se k=0, si ha bk=v0=b0= 1
Trasformazioni: bk = (v2)k/2 se k pari bk = v*vk-1 se k dispari
AN FI 98-99 Iterazione&Invarianti
bk : una soluzione a complessita’ log2(k)
boolean odd(int n){ return(n%2==1); }
double exp(double b,int k){
return (k==0) ? 1 :
( odd(k) ) ? b*exp(b,k-1)
: exp(b*b,k/2);
}
AN FI 98-99 Iterazione&Invarianti
bk in log2(k) : versione iterativa
bk = t*vn con v=b, t=1,n=k– Se n=0, si ha bk=t.
bk = t*(v2)n/2 se n pari
bk = t*v*vn-1 se n dispari
AN FI 98-99 Iterazione&Invarianti
Progetto versione iterativa log2(k)
double expIt(double b,int k,double t,double v,int n){
//Calcolare bk sapendo che bk = t*vn.
//Inizialmente e’ v=b, n=k,t=1. Se n=0, bk=t.return (n==0) ? t :
//Se n dispari, si itera con t=t*v ed n=n-1(odd(n)) ? expIt(b,k,t*v,v,n-1) :
//Se n pari si itera con v=v2 e n=n/2expIt(b,k,t,v*v,n/2)
le variabili b,k non servono
AN FI 98-99 Iterazione&Invarianti
Codice
double power( double b, int k ){ return (k==0) ? 1 : expIt(1,b,k); // bk = 1*bk }
double expIt(double t, double v, int n){//bk = t*vn
return (n==0) ? t : (odd(n)) ? // bk =t*v*vn-1
expIt(t*v,v,n-1) : // bk = t*(v2)n/2
expIt(t,v*v,n/2); }
AN FI 98-99 Iterazione&Invarianti
Un caso strano
int MulNat( int a, int b ){return MulNat(a,b,0); }
int MulNat( int x, int y, int z ){return(y == 0) ? z :
MulNat(x*2,y/2,z+x*(y%2));}
AN FI 98-99 Iterazione&Invarianti
Una diversa versione
int MulNat( int x, int y, int z ){return(y == 0) ? z : ( odd(y) ) ?
MulNat(x<<1,y>>1,z+x) :
MulNat(x<<1,y>>1,z);}
AN FI 98-99 Iterazione&Invarianti
La relazione di base
y = Q * B + R
B intero positivo Q=y/B (quoziente) R=y%B (resto)
AN FI 98-99 Iterazione&Invarianti
La moltiplicazione disgregata
p = x* y= x *(Q * B + R) = x*B*Q + x*R
pensando che x*R e x*B siano primitive, si deve calcolare x*Q
AN FI 98-99 Iterazione&Invarianti
L’algoritmo ricorsivo (B=2)
int MulNatR( int x, int y ){return (y == 0) ? 0 :
x*(y%2)+MulNatR(x*2, y/2);}
AN FI 98-99 Iterazione&Invarianti
Verso un invariante di ciclo
p = x*y + z = con y=0 si ha:
p = z
p = x*B*Q + x*R + zinizialmente z=0
AN FI 98-99 Iterazione&Invarianti
Il caso B=2
p = x*2*Q + x*R + zessendo Q=y/2 e R=y%2p = x*2*y/2 + x*y%2 + z
Ponendo x=x*2, y=y/2 e z=z+x*(y%2)
si riottiene la relazione di partenza p=x*y+z
AN FI 98-99 Iterazione&Invarianti
Il codice spiegato
int MulNat(int x,int y,int z){//a*b=x*y+z inizialmente x=a, y=b, z=0return(y == 0) ?
//a*b =x*y + z and y=0 => a*b=z z : //a*b = x*( y/2*2+y%2) + z =
//x*2*(y/2) + x*(y%2) + z MulNat(x*2,y/2,z+x*(y%2)); }
AN FI 98-99 Iterazione&Invarianti
La rappresentazione binaria
y%2=0 se y pari, y%2=1 se y dispari;
x*2 si ottiene spostando la rappresentazione binaria di x di una posizione a sinistra;
x/2 si ottiene spostando la rappresentazione binaria di x di una posizione a destra.
AN FI 98-99 Iterazione&Invarianti
L’algoritmo per moltiplicareint MulNat( int x, int y, int z ){
//a*b = x * y + z inizialmente x=a, y=b, z = 0return(y == 0) ? //a*b=x*y+z and y=0 => a*b=z
Z : (odd(y))?
//a*b=x*( y/2*2+y%2)+z and y dispari //a*b=x*2*y/2 + x*1 + z MulNat(x<<1,y>>1,z+x)
: //a*b = x*( y/2*2+y%2) + z and y pari //a*b = x*2*y/2 + x*0 + z
MulNat(x<<1,y>>1,z);}