Ricorsione iterazione
Download
1 / 100

RICORSIONE & ITERAZIONE - PowerPoint PPT Presentation


  • 84 Views
  • Uploaded on

m, se m=n. MCD(m, n) =. MCD(m-n, n), se m>n. MCD(m, n-m), se m<n. RICORSIONE & ITERAZIONE. Riconsideriamo l’esempio del Massimo Comun Divisore visto tempo addietro:. RICORSIONE & ITERAZIONE. Questo esempio era stato trasposto nella funzione seguente: int mcd(int m, int n){

loader
I am the owner, or an agent authorized to act on behalf of the owner, of the copyrighted work described.
capcha
Download Presentation

PowerPoint Slideshow about ' RICORSIONE & ITERAZIONE' - reuben


An Image/Link below is provided (as is) to download presentation

Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author.While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.


- - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - -
Presentation Transcript
Ricorsione iterazione

m, se m=n

MCD(m, n) =

MCD(m-n, n), se m>n

MCD(m, n-m), se m<n

RICORSIONE & ITERAZIONE

Riconsideriamo l’esempio del Massimo

Comun Divisore visto tempo addietro:


Ricorsione iterazione1
RICORSIONE & ITERAZIONE

Questo esempio era stato trasposto

nella funzione seguente:

int mcd(int m, int n){

return (m==n) : m ?

(m>n) ? mcd(m-n, n) : mcd(m, n-m);

}

L’esempio era particolare perché il risultato

veniva sintetizzato in avanti, anziché all’in-dietro come nei processi ricorsivi.


Ricorsione iterazione2
RICORSIONE & ITERAZIONE

  • Ogni processo computazionale che computi“in avanti”, per accumulo, costituisce una ITERAZIONEossia è unprocesso computazionale iterativo.

  • Ogni soluzione sintatticamente ricorsivache dia luogo a unprocesso computazio-nale iterativo costituisce una ricorsione solo apparente:una ricorsione tail.


Ricorsione iterazione3
RICORSIONE & ITERAZIONE

La caratteristica fondamentale di un

processo computazionale ITERATIVO

è che a ogni passo è disponibile un

risultato parziale

  • dopo k passi, si ha a disposizione il risultato parziale relativo al caso k

  • questo non è vero nei processi computazionali ricorsivi,in cui nulla è disponibile finché non si è disgregato il problema fino al caso elementare.


Il ragionamento iterativo
IL RAGIONAMENTO ITERATIVO

  • Si basa sulla disponibilità di una variabile, detta accumulatore, destinata a esprimere in ogni istante la soluzione corrente

  • Si imposta identificando quell’operazione di modifica dell’accumulatoreche lo porta a esprimere, dal valore relativo al passo k, il valore relativo al passo k+1.


Esempio calcolo del fattoriale
ESEMPIO: CALCOLO DEL FATTORIALE

Definizione:

n! = 1 * 2 * 3 *… * n

Detto vk = 1 * 2 * 3 *… * k:

1! = v1 = 1

(k+1)! = vk+1 = (k+1) * vkper k1

n! = vn per k=n


Esempio calcolo del fattoriale1
ESEMPIO: CALCOLO DEL FATTORIALE

int fact(int n){

return factIter(n,1,1);

}

int factIter(int n, int v, int k){

return (k==n) ? v : factIter(n, (k+1)*v, k+1);

}


Invarianti
INVARIANTI

Un invariante di programmaè una relazione

sempre vera in un dato punto del program-

ma.

Esempio:

double power(double b, int k){

return (k<=0) ? 1 : powerIt(b,k,b,1);

}

Invariante di programma:è sempre vero che qui k>0


Invarianti di ciclo
INVARIANTI DI CICLO

Un invariante di cicloè una relazione sem-

pre vera, in un dato punto del programma,

a ogni iterazione.

  • Identificare un invariante di ciclo è una forma di progetto.

  • Invarianti diversi suggeriscono di norma algoritmi diversi, che quasi sempre hanno diversa efficienza.


Problema calcolo di b k
PROBLEMA: CALCOLO DI bk

Un approccio iterativo

Posto bk = vk, si può scrivere:

b0= v0= 1 per i=0

bi = vi= b * bi-1 = b * vi-1per i>0

in particolare:

bk = vk per i=k

Un possibile invariante:bk = vi * bk-i


Problema calcolo di b k1
PROBLEMA: CALCOLO DI bk

Perché bk = bk-i *vi è un invariante?

Al generico passo 0<i<k, bk = vi* bk-i

Moltiplicando e dividendo per b:

bk = (vi*b) *bk-i-1 =vi+1* bk-(i+1)

che è l’invariante al passo (i+1)-esimo.

In particolare:

  • per i=0, bk = v0* bk = bkpurché v0 =1

  • per i=k, bk = vk* b0 = vk

condizione iniziale


Problema calcolo di b k2
PROBLEMA: CALCOLO DI bk

Come usarlo per progettare l’algoritmo?

  • inizialmente, v = v0 =1

  • a ogni passo si deve trasformare l’invariantebk = vi* bk-inella formabk =vi+1* bk-(i+1) che deve assumere al passo successivo

  • ciò si ottiene ponendo, a ogni passo

    v’ = b * v i’ = i + 1


Calcolo di b k l invariante
CALCOLO DI bk : L’INVARIANTE

double powerIt(double b, int k, double v, int i){

return (i==k) ? v :powerIt(b,k,v*b,i+1);

}

double power(double b, int k){

return (k==0) ? 1 : powerIt(b,k,1,0);

}

i’ = i+1

V’ = Vi+1= Vi* b

V0=1

i=0


Progettare b k per invarianti
PROGETTARE bk PER INVARIANTI

Partendo da relazioni diverse si ottengono

approcci diversi, con diversa efficienza.

Un diverso invariante:

  • k=0  b0 = 1

  • k>0

    k pari bk = (b2) k/2

    k dispari bk = b * bk-1

b*b: non richiede disaper fare potenze

richiede di saper fare un prodotto


Progettare b k per invarianti1
PROGETTARE bk PER INVARIANTI

Come usarlo per progettare l’algoritmo?

  • a ogni passo si deve riscriverebkin una delle due forme date

  • ciò si ottiene ponendo, a ogni passo

    • se k è pari: b’ = b * b k’ = k/2

    • se k è dispari: b’ = b k’ = k-1e moltiplicando per b

richiede una operazione dopo la fasedi modifica di b e k  soluzione ricorsiva


Progettare b k per invarianti2
PROGETTARE bk PER INVARIANTI

boolean odd(int n){return n%2==1;

}

double pow(double b, int k){

return (k==0) ? 1 :

odd(k) ? pow(b, k-1)* b:

pow(b*b, k/2);

}

ricorsionenon-tail

(Complessità dell’ordine di log2 k)


Progettare b k per invarianti3
PROGETTARE bk PER INVARIANTI

UN APPROCCIO ITERATIVO

Un ulteriore invariante:bk = t * vn

  • k=0  n=0, t=1 bk = t * v0 = 1

  • k>0

    • se n è pari: bk = t * (v2) n/2

    • se n è dispari: bk = t * v * vn-1


Progettare b k per invarianti4
PROGETTARE bk PER INVARIANTI

Progetto dell’algoritmo:

  • a ogni passo si deve trasformare l’invariantebk = t * vnin una delle due forme date

  • ciò si ottiene ponendo:

    • se n è pari  n’ = n/2,t’ = t,v’ = v2

    • se n è dispari  n’ = n-1,t’ = t*v,v’ = v

Interessante: b e k in realtà non si usano!


Progettare b k per invarianti5
PROGETTARE bk PER INVARIANTI

boolean odd(int n){return n%2==1;}

double powIt(double b, int k, double t, double v, int n){

return (n==0) ? t :

odd(n) ? powIt(b,k,t*v,v,n-1) :

powIt(b,k,t,v*v,n/2);

}

Come previsto, b e knon servono!Quindi li possiamo togliere…!!


Progettare b k per invarianti6
PROGETTARE bk PER INVARIANTI

boolean odd(int n){return n%2==1;}

double powIt(double t, double v, int n){

return (n==0) ? t :

odd(n) ? powIt(t*v, v, n-1) :

powIt(t, v*v, n/2);

}

double power(double b, int k){

return (k==0) ? 1 : powIt(1,b,k);

}


Esercizio moltiplicazione
ESERCIZIO: MOLTIPLICAZIONE

Obiettivo:

calcolare p = x* y

Sfruttiamo l’invariante:

y = Q * B + R

dove

  • B è un intero positivo

  • Q (quoziente) = y/B

  • R (resto) = y%B


Esercizio moltiplicazione1
ESERCIZIO: MOLTIPLICAZIONE

Obiettivo:

calcolare p = x* y

Sostituendo:

p = x * y= x*(Q * B + R)=

= x * (B * (y/B))+x*(y%B)

Caso particolare: y=0

p = x * y= x*0= 0


Esercizio moltiplicazione2
ESERCIZIO: MOLTIPLICAZIONE

Approccio ricorsivo:

si applica direttamente la relazione

trovatap = x*B * (y/B) ) + x*(y%B)

Ad esempio, scegliendo B=2:

int MulNatR(int x, int y){

return (y==0) ? 0 :

MulNatR(x*2, y/2) + x*(y%2);

}

Occorre fare un’operazione dopo la chiamata ricorsiva  ricorsione non-tail


Esercizio moltiplicazione3
ESERCIZIO: MOLTIPLICAZIONE

Approccio ricorsivo:

si applica direttamente la relazione

trovatap = x*B * (y/B) ) + x*(y%B)

Ad esempio, scegliendo B=2:

int MulNatR(int x, int y){

return (y==0) ? 0 :

MulNatR(x*2, y/2) + x*(y%2);

}

Operazione primitiva che suppo-niamo di saper già fare (è una moltiplicazione per 0 o per 1)

Operazioni primitive che supponiamo di sa-per già fare (moltiplicazione/divisione per 2)


Esercizio moltiplicazione4
ESERCIZIO: MOLTIPLICAZIONE

Verso un approccio iterativo

Cerchiamo un invariante di ciclo

p = x * y + z

Ponendo y=Q*B+Re trasformando:

p = (x*B) * Q + (x*R + z) = x’ * y’ + z’

dove si è posto

y’ = Q = y/B,x’ = x*B,z’ = z + x*R

Caso particolare: y=0  p = z


Esercizio moltiplicazione5
ESERCIZIO: MOLTIPLICAZIONE

Invariante di ciclo: p = x * y + z

Trasformazione: p = x’ * y’ + z’

y’ = Q = y/B,x’ = x*B,z’ = z + x*R

int MulNatIt(int x, int y, int z){

return(y==0) ? z :

MulNatIt(x*2, y/2, z+x*(y%2));

}

Operazioni primitive: supponiamo di saper giàmoltiplicare, dividere e modulare per 2.


Esercizio moltiplicazione6
ESERCIZIO: MOLTIPLICAZIONE

Perché supponiamo di saper già moltiplicare,

e dividere per 2 (trovando anche il resto) ?

Perché l’elaboratore è intrinsecamente capace

di farlonella propria ALU:

  • moltiplicazione per 2 = shift a sinistra (<<)

  • divisione per 2 = shift a destra (>>)

  • moltiplicazione per (y%2) = 0, se y è pari (y%2 vale 0) y, se y dispari (y%2 vale 1)


Esercizio moltiplicazione7
ESERCIZIO: MOLTIPLICAZIONE

Il codice finale che ne risulta:

int MulNatIt(int x, int y, int z){

return (y==0) ? z :

odd(y):

MulNatIt(x<<1, y>>1, z+x) :

MulNatIt(x<<1, y>>1, z);

}

boolean odd(int n){return n%2==1;}

y%2 = 1

x/2

y/2

y%2 = 0


Una riflessione di fondo
UNA RIFLESSIONE DI FONDO

  • L’impostazione funzionale è sempre costruttiva. Ma si può sempre solo creare?

  • Perché creare una versione nuova di un accumulatore ad ogni passo, quando l’elaboratore di Von Neumann permette la modificadel contenuto di una cella di memoria?


Una proposta
UNA PROPOSTA

  • È possibile riusare una stessa area datisenza bisogno di crearne una nuova ad ogni passo computazionale?

  • Ci sono controindicazioni?


Variabili nei linguaggi imperativi
VARIABILI NEI LINGUAGGI IMPERATIVI

Una variabilein un linguaggio imperativo

  • non è solo un sinonimo per un datocome in matematica

  • è un’astrazione della cella di memoria

  • associata a due diverse informazioni:

    • il contenuto (R-value)

    • l’indirizzo a cui si trova (L-value)

3.22

a

x


Espressioni con effetti collaterali
ESPRESSIONI CON EFFETTI COLLATERALI

  • Le espressioni che contengono variabili, oltre a denotare un valore,possono a volte comportare effetti collaterali sulle variabili coinvolte.

  • Un effetto collaterale è una modifica del valore della variabile (R-value) causato da particolari operatori:

    • operatore di assegnamento

    • operatori di incremento e decremento


Assegnamento
ASSEGNAMENTO

  • L’assegnamento è un particolare tipo di espressione

    • come tale denota comunque un valore!!

      con un effetto collaterale:quello di cambiare il valore della variabile.

  • Sintassi

    variabile = espressione

  • Esempi di espressioni di assegnamento:

    j = 0 k = j + 1


Assegnamento1
ASSEGNAMENTO

L’espressione di assegnamento

variabile = espressione

  • denota il valore dell’ espressione

  • ma cambia anche il valore della variabile: il nuovo valore della variabile è quello denotato dalla espressione.


Esempio
ESEMPIO

Se k valeva 2, l’espressione

k = 7

  • denota il valore 7

  • e cambia il valore di k,che d’ora in poi vale 7 (non più 2)


Esempio1
ESEMPIO

Se k valeva 2, l’espressione

j = k+1

  • denota il valore 3

  • e cambia il valore di j,che d’ora in poi vale 3 (qualunque valore avesse prima)

    L’assegnamento è distruttivo


Espressioni di assegnamento
ESPRESSIONI DI ASSEGNAMENTO

Il valore denotato dall’espressione di

assegnamento può essere usato in altre

espressioni.Ad esempio,

3 + (k=7)

  • denota il valore 10

  • e cambia in 7 il valore di k


Assegnamento variabili
ASSEGNAMENTO & VARIABILI

Una variabilein una espressione di

assegnamento:

  • è intepretata come il suo R-value, se compare a destra del simbolo =

  • è intepretata come il suo L-value, se compare a sinistra del simbolo =

3.22

a

x


Esempio2
ESEMPIO

Se x valeva 2, l’espressione

x = x + 1

  • denota il valore 3

  • e cambia in 3 il valore di x

    • il simbolo x a destra dell’operatore = denota il valore attuale (R-value) di x, cioè 2

    • il simbolo x a sinistra dell’operatore = denota la cella di memoria associata a x (L-value), a cui viene assegnato il valore dell’espressione di destra (3)

    • l’espressione nel suo complesso denota il valore della variabile dopo la modifica, cioè 3.


Assegnamento associativit
ASSEGNAMENTO: ASSOCIATIVITÀ

  • Come tutti gli operatori, anche l’operatore di assegnamento deve avere una sua associatività

    k = j = 1

    Prima k=j, o prima j=1 ?

  • l’operatore di assegnamento è associativo a destra: ciò consente espressioni di assegnamento multiplo


Assegnamento associativit1
ASSEGNAMENTO: ASSOCIATIVITÀ

Esempi

k = j = 1interpretato come k = (j = 1)

i = j = k = 0interpretato come i = (j = (k=0))

i = k + 5 = 6NO: k+5 non ha un L-value!

Nota: anche volendo, sarebbe stato impossibile farlo

associativo a sinistra, in quanto ciò avrebbe reso

molte espressioni prive di significato. Ad esempio:

k = j = 2 interpretato come (k=j) = 2 ???

Equivarrebbe a scrivere 1 = 2 !!!!


Incremento e decremento
INCREMENTO (++) E DECREMENTO (--)

Gli operatori di incremento e decremento

sono usabili in due modi

  • come pre-operatori: ++v

  • come post-operatori: v++

primaincremento, poiuso

primauso, poiincremento


Esempi
ESEMPI

int i, j, k = 5;

i = ++k /* i vale 6, k vale 6 */

i = k++ /* i vale 5, k vale 6 */

int i=4, j, k = 5;

j = i + k++; /* j vale 9, k vale 6 */

j = ++k - k++; /* in cerca di guai! */


Attenzione
ATTENZIONE…!!

int k = 6;

j = ++k - k++; /* in cerca di guai! */

Detti x = ++k e y = k++,

  • è certo che l’espressione venga valutata come j = x - y (da sinistra a destra)

  • è certo che alla fine k valga 8

  • ma non si sa se venga calcolato prima x o prima y,e qui la cosa fa molta differenza!

    • se prima x, poi y  j = 7 - 7 = 0

    • se prima y, poi x  j = 8 - 6 = 2


Un esempio
UN ESEMPIO

Ad esempio, se c vale 20, l’espressione vale 68...

main() {

int f, c = 20;

f = 32 + c * 9 / 5;

}

L’espressionef = 32 + c * 9 / 5

  • recupera l’ R-value della variabile c

  • calcola il corrispondente valore Fahrenheit e lo assegna alla variabile f (interpretata come L-value effetto collaterale)

  • scarta il valore denotato dall’espressione di assegnamento (che non viene più utilizzato)

… quindi a f viene asse-gnato il valore 68.

L’espressione f=68 denotaancora 68, che però vienescartato.


Istruzioni
ISTRUZIONI

  • Le istruzioni esprimono azioni che, una volta eseguite, comportano una modifica permanente dello stato interno del pro-gramma o del mondo circostante.

  • Le strutture di controllo permettono di aggregare istruzioni semplici in istruzioni più complesse.


Istruzioni1
ISTRUZIONI

  • Una istruzione C è espressa dalle seguenti produzioni:

    <istruzione> ::= <istruzione-semplice>

    <istruzione> ::= <istruzione-di-controllo>

    <istruzione-semplice> ::= <espressione>;

  • Quindi, qualsiasi espressione seguita da un punto e virgola è una istruzione semplice.


Esempi di istruzioni semplici
ESEMPI DI ISTRUZIONI SEMPLICI

x = 0; y = 1; /* due istruzioni */

x = 0, y = 1; /* una istruzione */

k++;

3; /* non fa nulla */

; /* istruz. vuota*/


Istruzioni di controllo
ISTRUZIONI DI CONTROLLO

Una istruzione di controllo può essere:

  • una istruzione composta (blocco)

  • una istruzione condizionale (selezione)

  • una istruzione di iterazione(ciclo)

    come specificato dalla produzione:

    < istruzione-di-controllo > ::=<blocco> | <selezione> | <iterazione>


Istruzioni di controllo1
ISTRUZIONI DI CONTROLLO

Le istruzione di controllo sono alla base della

programmazione strutturata(Dijkstra, 1969).

Concetti chiave:

  • concatenazioneocomposizione

  • selezione o istruzione condizionaleramifica il flusso di controllo in base al valore vero o falso di una espressione (“condizione di scelta”)

  • ripetizione o iterazioneesegue ripetutamente un’istruzione finché rimane vera una espressione (“condizionedi iterazione”)


Teorema di jacopini b hm
TEOREMA DI JACOPINI-BÖHM

  • Le strutture di concatenazione, iterazione e selezione costituisconoun insieme completoin grado di esprimere tutte le funzioni calcolabili.

  • Dunque, l’uso di queste sole strutture di controllo non limita il potere espressivo.

  • La dimostrazione del teorema è basata sulla Turing-equivalenza di un “mini-linguaggio” che fornisca solo tali strutture di controllo.


Blocco
BLOCCO

<blocco> ::={

[ <dichiarazioni e definizioni> ]

{ <istruzione> }

}

  • dopo un blocco non occorre il punto e virgola (esso termina le istruzioni semplici, non separa istruzioni)

Lo scope dei simboli che compaiono entro il blocco è il blocco stesso


Esempio di blocco
ESEMPIO DI BLOCCO

main() {/* INIZIO BLOCCO */

const float F1=9.0, F2=5, SH=32;

int c, f, temp = 20;

char scala = 'C';

c = (scala != 'F') ? temp

: (F2 / F1 * (temp - SH)) ;

f = (scala != 'F') ? (SH+temp*F1/F2) : temp;

}/* FINE BLOCCO */


Una nota en passant
..una nota “en passant”...

main() { /* INIZIO BLOCCO */

const float F1=9.0, F2=5, SH=32;

int c, f, temp = 20;

char scala = 'C';

c = (scala != 'F') ? temp

: (F2 / F1 * (temp - SH)) ;

f = (scala != 'F') ? (SH+temp*F1/F2) : temp;

} /* FINE BLOCCO */

Il qualificatore const rendequeste variabili non modificabili


Esempio di blocchi annidati
ESEMPIO DI BLOCCHI ANNIDATI

main() {/* INIZIO BLOCCO ESTERNO */

const float F1=9.0, F2=5, SH=32;

int c, f, temp = 20;

{/* INIZIO BLOCCO INTERNO */

char scala = ‘C’;

c = (scala != 'F') ? temp

: (F2 / F1 * (temp - SH)) ;

f = (scala != 'F') ? (SH+temp*F1/F2) : temp;

}/* FINE BLOCCO INTERNO */

}/* FINE BLOCCO ESTERNO */


Istruzioni condizionali
ISTRUZIONI CONDIZIONALI

<selezione> ::=

<scelta> | <scelta-multipla>

  • la seconda non è essenziale, ma migliora l’espressività.

  • l’espressione condizionale ternaria (.. ? … : …) fornisce già un mezzo per fare scelte, ma è poco leggibile in situazioni di medio/alta complessità. L’istruzione di scelta fornisce un altro modo per esprimere alternative.


Istruzione di scelta semplice

vera

falsa

condizione

istruzione1

istruzione2

ISTRUZIONE DI SCELTA SEMPLICE

<scelta> ::=if<condizione> <istruzione1> [else <istruzione2> ]

Una espressione logica o relazionale,che viene valutata al momento dellaesecuzione dell’istruzione if.


Istruzione di scelta semplice1

vera

falsa

condizione

istruzione1

istruzione2

ISTRUZIONE DI SCELTA SEMPLICE

<scelta> ::=if<condizione> <istruzione1> [else <istruzione2> ]

La parte else è opzionale:se omessa, in caso dicondizione falsa si passasubito all’istruzione chesegue l’if.


Esempio di istruzione if
ESEMPIO DI ISTRUZIONE if

  • <istruzione1> e <istruzione2> sono ciascuna una singola istruzione

  • Qualora occorra specificare più istruzioni, si deve quindi utilizzare un blocco.

    if (n > 0){ /* inizio blocco */

    a = b + 5;

    c = (x<3) ? a : b;

    } /* fine blocco */else n = b;


Istruzione if annidate
ISTRUZIONE if ANNIDATE

  • Come caso particolare, <istruzione1> o <istruzione2> potrebbero essere un altro if

  • Occorre attenzione ad associare le parti else (che sono opzionali) all’ if corretto

    if (n > 0)

    if (a>b) n = a;

    else n = b; /* riferito a if(a>b) */

    if (n > 0)

    { if (a>b) n = a; }

    else n = b; /* riferito a if(n>0) */

Regola semantica:l’else è sempre associato all’if più interno

Se ciò non soddisfa occor-re inserire esplicitamenteun blocco.


Istruzione di scelta multipla

espressione di selezione

caso A

break

istruzioni1

caso B

break

istruzioni2

break

default

istruzioni

ISTRUZIONE DI SCELTA MULTIPLA

  • Consente di scegliere fra molte istruzioni (alternative o meno) in base al valore di una espressione di selezione.

  • L’espressione di sele-zione deve denotare un valore numerabile (intero, carattere,…).


Istruzione di scelta multipla1
ISTRUZIONE DI SCELTA MULTIPLA

Se nessuna etichetta corri-sponde, si prosegue col ilramo default.

<scelta-multipla> ::=

switch(selettore){case<etichetta1>:< istruzioni> [break;]

case<etichetta2>:< istruzioni> [break;]…[default:< istruzioni> ]

}

Il valore dell’espressione selettoreviene confron-

tato con le etichette dei vari casi: l’esecuzione

prosegue dal ramo corrispondente (se esiste).

Se neanche quello esiste, si prosegue con l’istruzionesuccessiva allo switch.


Istruzione di scelta multipla2
ISTRUZIONE DI SCELTA MULTIPLA

Le etichette sono costantidello stesso tipo del selettore.

<scelta-multipla> ::=

switch(selettore){case<etichetta1>:< istruzioni> [break;]

case<etichetta2>:< istruzioni> [break;]…[default:< istruzioni> ]

}

Il valore dell’espressione selettoreviene confron-

tato con le etichette dei vari casi: l’esecuzione

prosegue dal ramo corrispondente (se esiste).

Attenzione: <istruzioni>denota una sequenza di istruzioni (non occorre un blocco)


Istruzione di scelta multipla3

espressione di selezione

caso A

break

istruzioni1

caso B

break

istruzioni2

break

default

istruzioni

ISTRUZIONE DI SCELTA MULTIPLA

I vari rami non sono mutua-mente esclusivi: imboccato un ramo, si eseguono anche tutti i rami successivi...

… a meno che non ci siail comando break a forzareesplicitamente l’uscita.


Istruzioni di iterazione
ISTRUZIONI DI ITERAZIONE

<iterazione> ::=

<while> | <for> | <do-while>

  • Per il Teorema di Jacopini-Böhm, una struttura di controllo iterativa sarebbe sufficiente: averne di più migliora l’espressività del linguaggio.

  • Le istruzioni di iterazione:

    • hanno un solo punto di ingresso e un solo punto di uscita nel flusso del programma

    • perciò possono essere interpretate come una singola azione in una computazione sequenziale.


Istruzione while

falsa

condizione

vera

istruzione

ISTRUZIONE while

<while> ::=while(<condizione>)<istruzione>

L’istruzione viene ripetuta pertutto il tempo in cui la condi-zione rimane vera.

Se la condizione è falsa, l’itera- zione non viene eseguita neppure una volta.

In generale, non è noto quantevolte l’istruzione sarà ripetuta.


Istruzione while1

falsa

condizione

vera

istruzione

ISTRUZIONE while

Prima o poi, direttamente oindirettamente, l’istruzione deve modificare la condizione:altrimenti, l’iterazione dureràper sempre!

<while> ::=while(<condizione>)<istruzione>

Perciò, quasi sempre istruzioneè un blocco, al cui interno simodifica qualche variabileche compare nella condizione.


Istruzione do while

istruzione

falsa

condizione

vera

ISTRUZIONE do...while

<do-while> ::=do <istruzione>while(<condizione>);

È una “variazione sul tema” della precedente: la condizione viene verificata dopo aver eseguito l’istruzione.

Se la condizione è falsa, l’itera- zione viene comunque ese-guita almeno una volta.

particolarmente adatta alleverifiche dopo un input


Istruzione for
ISTRUZIONE for

È una evoluzione dell’istruzione while

rispetto a cui mira a eliminare alcune

frequenti sorgenti di errore:

  • mancanza delle necessarie inizializza-zionidelle variabili

  • mancanza della fase di modifica del ciclo(rischio di ciclo senza fine)


Istruzione for1

espr-inizializzazione

falsa

condizione

Struttura del while

vera

istruzione

espr-modifica

ISTRUZIONE for

<for> ::=for(<espr-i>;<cond>; <espr-m>)<istruzione>


Istruzione for2

espr-inizializzazione

falsa

condizione

vera

istruzione

espr-modifica

ISTRUZIONE for

<for> ::=for(<espr-i>;<cond>; <espr-m>)<istruzione>

Espressione di inizia-lizzazione:valutata una e una sola volta prima di iniziare l’itera-zione.

Espressione di inizia-lizzazione: valutata una e una sola volta primadi iniziare l’itera-zione.


Istruzione for3

espr-inizializzazione

falsa

condizione

vera

istruzione

espr-modifica

ISTRUZIONE for

<for> ::=for(<espr-i>;<cond>; <espr-m>)<istruzione>

Condizione:valutata a ogni interazione,per decidere se proseguire(come in un while)Se manca si assume vera!

Condizione:valutata a ogni interazione,per decidere se proseguire(come in un while)


Istruzione for4

espr-inizializzazione

falsa

condizione

vera

istruzione

espr-modifica

ISTRUZIONE for

<for> ::=for(<espr-i>;<cond>; <espr-m>)<istruzione>

Condizione:valutata a ogni interazione,per decidere se proseguire(come in un while)

Espressione di modifica:valutata a ogni interazione,dopo aver eseguito l’istru-zione.


Un esempio1
UN ESEMPIO

Il solito problema: calcolo del fattoriale

  • Dall’approccio ricorsivo…

  • ...all’approccio sintatticamente ricorsivo, ma computazionalmente iterativo(ricorsione tail)...

  • ...all’approccio iterativo tramite istruzioni di iterazione.


Il fattoriale iterativo tramite espressione condizionale
IL FATTORIALE ITERATIVO TRAMITE ESPRESSIONE CONDIZIONALE...

int factIter(int n, int i, int v){

/* inizialmente, v = 1 */

/* invariante di ciclo: v = i! */

return (i==n) ? v : factIter(n,i+1,(i+1)*v);

}

Chiamata:factIter(n,0,1)


Il fattoriale iterativo tramite istruzione condizionale
... IL FATTORIALE ITERATIVO TRAMITE ISTRUZIONE CONDIZIONALE...

int factIter(int n, int i, int v){

/* inizialmente, v = 1 */

/* invariante di ciclo: v = i! */

if (i==n) return v;

else return factIter(n,i+1,(i+1)*v);

}

Chiamata:factIter(n,0,1)


Il fattoriale iterativo tramite istruzione di iterazione while
...IL FATTORIALE ITERATIVO TRAMITE ISTRUZIONE DI ITERAZIONE: while

int fact(int n){

int v=1; /* inizialmente, v = 1 */

int i=0; /* inizialmente, i = 0 */

while(i<n) {/* invariante: v = i! */

v = (i+1)*v;

i = i+1;

}

return v;

}

I valori iniziali, prima forniti dl-l’esterno, divengono ora varia-bili locali della funzione interfaccia utente più pulita


Il fattoriale iterativo tramite istruzione di iterazione do while
...IL FATTORIALE ITERATIVO TRAMITE ISTRUZIONE DI ITERAZIONE: do...while

int fact(int n){

int v=1; /* inizialmente, v = 1 */

int i=0; /* inizialmente, i = 0 */

do {/* invariante: v = i! */

v = (i+1)*v;

i = i+1;

} while(i<n);

return v;

}

La condizione è ora verificatadopo ogni interazione anzichéprima.

Problema: che succede se siinvoca fact(-3) ???


Il fattoriale iterativo tramite istruzione di iterazione for
...IL FATTORIALE ITERATIVO TRAMITE ISTRUZIONE DI ITERAZIONE: for

int fact(int n){

int v=1;/* inizialmente, v = 1 */

int i;

for(i=0;i<n;i=i+1) v = (i+1)*v; /* invariante: v = i! */

return v;

}

Le fasi di inizializzazione e dimodifica della variabile di con-trollo del ciclo sono ben in evi-denza nella struttura del for.


Iterazione ricorsione tail
ITERAZIONE & RICORSIONE TAIL

Poiché la ricorsione tail dà luogo a un processo computazionale di tipo iterativo, deve essere possibile trasformare un ciclo in ricorsione tail e viceversa.

COME FARLO?

  • il corpo del ciclo rimane immutato

  • il ciclo diventa un if con, in fondo, la chiamata tail-ricorsiva.


Iterazione ricorsione tail1
ITERAZIONE & RICORSIONE TAIL

  • il corpo del ciclo rimane immutato

  • il ciclo diventa un if con, in fondo, la chiamata tail-ricorsiva.

    Naturalmente, può essere necessario aggiungere nuovi parametri nell’intestazione della funzione tail-ricorsiva, per “portare avanti” le variabili di stato.


Esempio massimo comun divisore
ESEMPIO: Massimo Comun Divisore

La soluzione tail-ricorsiva già vista...

int mcd(int m, int n){

if (m!=n) if (m>n) return mcd(m-n, n); else return mcd(m, n-m);

else return m;

}

… opportunamente riscritta...

int mcd(int m, int n){

if (m!=n) {

if (m>n) m=m-n; else n=n-m;

return mcd(m,n);

} else return m;

}


Esempio massimo comun divisore1
ESEMPIO: Massimo Comun Divisore

… opportunamente riscritta...

int mcd(int m, int n){

if (m!=n) {

if (m>n) m=m-n; else n=n-m;

return mcd(m,n);

} else return m;

}

… traslata in ciclo:

int mcd(int m, int n){

while (m!=n)

if (m>n) m=m-n; else n=n-m;

return m;

}


Esercizio 1
ESERCIZIO 1

Dati tre valori a b c che rappresentano le lunghezze di tre segmenti, valutare se posso-no essere i tre lati di un triangolo, e se sì deci-derne il tipo (scaleno, isoscele, equilatero).

Vincolo: deve essere c < (a+b)

Rappresentazione delle informazioni:

  • la variabile booleana triangolo indica se i tre seg- menti possono costituire un triangolo

  • le variabili booleane scaleno, isoscele e equilindicano il tipo di triangolo.


Esercizio 11
ESERCIZIO 1

Specifica:

se a+b>c

triangolo = vero

se a=b=c { equil=isoscele=vero scaleno=falso }

altrimenti

se a=b o b=c o a=c { isoscele=vero; equil=scaleno=falso }

altrimenti

{ scaleno=vero; equil=isoscele=falso }

altrimenti triangolo = falso


Esercizio 12
ESERCIZIO 1

main (){

float a=1.5, b=3.0, c=4.0;

int triangolo, scaleno, isoscele, equil;

triangolo = (a+b>c);

if (triangolo) {

if (a==b && b==c) { equil=isoscele=1; scaleno=0; }

else if (a==b || b==c || a==c) { isoscele=1; scaleno=equil=0;} else { scaleno=1; isoscele=equil=0;}

}

}


Esercizio 13
ESERCIZIO 1

Non si può usare l’istruzione di scelta multipla (switch) perchéle condizioni da verificare sonouguaglianze fra variabili, nonsemplici confronti con etichettepredefinite.

main (){

float a=1.5, b=3.0, c=4.0;

int triangolo, scaleno, isoscele, equil;

triangolo = (a+b>c);

if (triangolo) {

if (a==b && b==c) { equil=isoscele=1; scaleno=0; }

else if (a==b || b==c || a==c) { isoscele=1; scaleno=equil=0;} else { scaleno=1; isoscele=equil=0;}

}

}

Attenzione! Una espressionecome a==b==c sarebbe stataformalmente lecita, ma avreb-be avuto tutt’altro significato!


Esercizio 2
ESERCIZIO 2

Dati due valori positivi X e Y, calcolarne la

divisione intera X/Y come sequenza di

sottrazioni, ottenendo quoziente e resto.

Invariante di ciclo:

X = Q * Y + R, con R  0

  • inizialmente, Q=0, R=X (R>Y)

  • a ogni passo, Q’=Q+1, R’=R-Y (R>Y)

  • alla fine, X = Q(n) * Y + R (n) (0<R<Y)che è la definizione di divisione intera.


Esercizio 21
ESERCIZIO 2

Notare l’uso di una espressioneconcatenata per concatenare dueassegnamenti e inizializzare cosìdue variabili.

Specifica:

sia Q il quoziente, inizialmente pari a 0sia R il resto, inizialmente pari a X

while (R  Y)

incrementare il quoziente Q

decrementare R di una quantità Y

Codifica

main(){

int x = 20, y = 3, q, r;

for (q=0, r=x; r>=y; q++, r=r-y);

}

Idem per le operazionidi modifica


Operatori di assegnamento compatti
OPERATORI DI ASSEGNAMENTO “COMPATTI”

Il C introduce una forma particolare di assegnamento che ingloba anche un’operazione aritmetica o bit a bit:

l-espr=<espressione>

è “quasi equivalente” a

l-espr=l-espr<espressione>

dove  indica un operatore fra+, –, *, /, %, >>, <<, &, ^, |


Operatori di assegnamento compatti1
OPERATORI DI ASSEGNAMENTO “COMPATTI”

Perché “quasi” equivalente ?

  • nel primo caso, l-espr viene valutata una sola volta

  • nel secondo, invece, viene valutata due volte

  • Quindi, le due forme sono equivalenti solo se la valutazione di l-esprnon comporta effetti collaterali


Operatori di assegnamento compatti2
OPERATORI DI ASSEGNAMENTO “COMPATTI”

Esempi

k += j equivale a k = k + j

k *= a + b equivale a k = k*(a+b)*/

v[i++] *= n non equivale a v[i++] = v[i++]*n */


Esercizio 3
ESERCIZIO 3

Dati tre valori a, b, c, rappresentanti i coeffi-cienti di un’equazione di secondo grado a x2 + b x + c = 0, calcolarne le radici (reali).

Specifica:

Calcolare il valore delta = b2 - 4ac

Se delta0

calcolare d = deltacalcolare le due radici x1, x2 = - (bd) / 2a

altrimenti (radici complesse: halt)


Esercizio 31
ESERCIZIO 3

#include <math.h>

main (){

float a=1.0, b=2.0, c=-15.0;

float delta, d, x1, x2;

delta = b*b-4*a*c;

if (delta>=0){

d = sqrt(delta);

x1 = -(b+d)/(2*a);

x2 = -(b-d)/(2*a);

}

}

Direttiva al preprocessore: include la libreria matematica(fornisce la funzione sqrt)


Esercizio 4
ESERCIZIO 4

Scrivere una funzione che verifichi se un naturale N è primo.

Specifica di I° livello (Crivello di Eratostene):

Occorre provare a dividere N per tutti i numeri K N: se nessuno risulta essere un divisore, allora N è primo

Specifica di II° livello:

Se N è 1, 2 o 3, allora è primo senz’altro. Altrimenti, se è un numero pari, non è primo.Se invece N è dispari e >3, occorre tentare tutti i possibili divisori da 3 in avanti, fino a N.


Esercizio 41
ESERCIZIO 4

#include <math.h>

int isPrime(int n) {

int max,i;

if (n>=1 && n<=3) return true;/* 1,2,3  ok */

if (n%2==0) return false;/* numeri pari  no */

max = sqrt(n);

for(i=3; i<=max; i+=2)

if (n%i==0) return false;

return true;

}


Esercizio 5
ESERCIZIO 5

Scrivere una funzione radice che calcoli la radice quadrata (intera) di un naturale N.

Specifica di I° livello:

int radice(int n);restituisce il massimo intero X tale che X*X  N

Specifica di II° livello:

Considera un naturale X dopo l’altro a partire da 1, e calcolane il quadrato X*X: fermati appena tale quadrato supera N.Il precedente numero considerato (X-1) è il risultato.


Esercizio 51
ESERCIZIO 5

int radice(int n) {

int x;

for(x=0; x*x <= n; x++);

return x-1;

}

Il corpo del ciclo è vuoto: ineffetti, l’elaborazione consistesolo nell’incrementare x perun opportuno numero di volte.


Esercizio 6
ESERCIZIO 6

Scrivere una funzione che, dato un carattere C, restituisca il corrispondente maiuscolo.

Specifica di I° livello:

char maiuscolo(char c);restituisce il maiuscolo di C

Specifica di II° livello:

Se C non è una lettera minuscola, restituiscilo tale e quale. Altrimenti, per calcolare il corrispondente maiu-scolo, sfrutta l’ ordinamento della codifica dei caratteri:– ogni carattere è associato a un intero– le lettere da ‘A’ a ‘Z’ sono in sequenza– le lettere da ‘a’ a ‘z’ sono in sequenza


Esercizio 61
ESERCIZIO 6

char maiuscolo(char c) {

if (c<'a' || c>'z') return c;

else return c – 'a' + 'A';

}

Aritmetica fra caratteri: possibileperché le operazioni vengonosvolte sul corrispondente codice(ASCII o UNICODE)

Attenzione! Una espressione come 'a’<c<'z'è lecita, ma ha tutt’altro significato!


ad