{Questo programma legge un intero da terminale e scrive su terminale il fattoriale dell'intero letto. Se l'intero digitato e' negativo restituisce 1.} var n:integer; {Memorizza l'input} f:integer; {Memorizza risultati intermedi e output} i:integer; {Contatore usato nel ciclo while} begin writeln('Questo programma calcola il fattoriale di un intero non negativo.'); writeln('Digita l'intero:'); readln(n); i:=0; f:=1; while (n>i) do {0<=i<=max(0,n) and f=i!} begin i:=i+1; f:=f*i; end; {se n<0 allora i=0, quindi f=1. se n>=0 allora i=n, quindi f=n!.} writeln('Il fattoriale di',n); writeln('e`',f); end.
Controllo sull'input
{Questo programma legge un intero non negativo da terminale e scrive su terminale il fattoriale dell'intero letto. Se l'intero digitato e' negativo chiede all'utente di reimmettere l'input.} var n:integer; {Memorizza l'input} f:integer; {Memorizza risultati intermedi e output} i:integer; {Contatore usato nel ciclo while} begin writeln('Questo programma calcola il fattoriale di un intero non negativo.'); {Commento riservato a chi non conosce il ciclo repeat: il ciclo viene sempre eseguito la prima volta, si esce quando la condizione dopo until diventa VERA} repeat begin writeln('Digita un intero non negativo:'); readln(n); end until (n>=0); {------------------------------------} i:=0; f:=1; while (n>i) do {0<=i<=n and f=i!} begin i:=i+1; f:=f*i; end; {f=n!} {------------------------------------} writeln('Il fattoriale di',n); writeln('e`',f); end.
Prima di fare questo esercizio puo' essere utile ricordare che (in Turbo Pascal):
for j:=h to k do begin S end;e' equivalente a:
j:=h; while j<=k do begin S; j:=j+1; end;
Vediamo ora una delle possibili soluzioni all'esercizio proposto:
{------------------------------------} f:=1; if n>=2 then for i:=2 to n do f:=i*f; {2<=i<=n and f=i!} {f=n!} {------------------------------------}
E' facile verificare che il controllo "if n>=2" puo' essere eliminato (in ogni caso, se n<2, il ciclo for e' eseguito 0 volte):
{------------------------------------} f:=1; for i:=2 to n do f:=i*f; {2<=i<=n and f=i!} {f=n!} {------------------------------------}
Per capire l'invariante, traduciamo il for in un while:
{------------------------------------} f:=1; i:=2; while i<=n do begin f:=i*f; {2<=i<=n and f=i!} i:=i+1; end; {f=n!} {------------------------------------}
Se ora vogliamo spostare l'asserzione nel punto in cui viene eseguito il test, che il punto "standard" dove si mette l'invariante di ciclo per il while, e' sufficiente osservare che, dopo aver eseguito l'incremento i:=i+1, il "valore di i prima dell'incremento" e' dato da "valore di i (dopo l'incremento)"-1. Abbiamo quindi (osservate che, per far si che l'invariente sia vero anche la prima volta che si arriva al ciclo (quando i=2), abbiamo dovuto cambiare il 2 in 1 e (per il caso n=0) l'n in max(1,n)):
{------------------------------------} f:=1; i:=2; while i<=n do {0<=i-1<=max(1,n) and f=(i-1)!} begin f:=i*f; i:=i+1; end; {f=n!} {------------------------------------}
Prima di fare questo esercizio puo' essere utile ricordare che
repeat begin S end until C;e' equivalente a:
S; while (not C) do begin S end;
Vediamo ora una delle possibili soluzioni all'esercizio proposto:
{------------------------------------} i:=n; f:=1; if n>0 then repeat begin f:=f*i; i:=i-1; end; until (i=0); {0<=i<=n and f*(i!)=n!} {f=n!} {------------------------------------}
{Questo programma legge un intero non negativo da terminale e scrive su terminale il fattoriale dell'intero letto. Se l'intero digitato e' negativo chiede all'utente di reimmettere l'input.} var n:integer; {Memorizza l'input} f:integer; {Memorizza l'output} {INSERITE QUI LA PROCEDURA fatt VISTA A LEZIONE (VEDI PAGINA WEB), METTETE L'INVARIANTE MIGLIORATO, RIPORTATO NELLA SOLUZIONE DELL'Esercizio 1} begin writeln('Questo programma calcola il fattoriale di un intero non negativo.'); repeat begin writeln('Digita un intero non negativo:'); readln(n); end until (n>=0); {n>=0} fatt(n,f); {f=n!} writeln('Il fattoriale di',n); writeln('e`',f); end.
{Questo programma legge un intero non negativo da terminale e scrive su terminale il fattoriale dell'intero letto. Se l'intero digitato e' negativo chiede all'utente di reimmettere l'input.} var n:integer; {Memorizza l'input} {INSERITE QUI LA FUNZIONE fatt VISTA A LEZIONE (VEDI PAGINA WEB), METTETE L'INVARIANTE MIGLIORATO, RIPORTATO NELLA SOLUZIONE DELL'Esercizio 1} begin writeln('Questo programma calcola il fattoriale di un intero non negativo.'); repeat begin writeln('Digita un intero non negativo:'); readln(n); end until (n>=0); writeln('Il fattoriale di',n); writeln('e`',fatt(n)); end.
{Questo programma legge da terminale un intero non negativo n, poi legge n interi non negativi, e stampa su terminale il fattoriale della media aritmetica (usa div per fare la divisione). Se l'utente digita un intero negativo il programma chiede all'utente di reimmettere l'input.} const Imax = 100; {Numero massimo di elementi permessi in input} type VettInt = array [1..Imax] of integer; var n:integer; {Memorizza il numero di interi forniti in input} a:VettInt; {Memorizza gli interi} {Legge da terminale un intero compreso tra inf e sup e lo restituisce in i. Se l'intero letto non rispetta il range, chiede all'utente di reimmetterlo. Se inf>sup continua a chiedere valori.} procedure leggiIntero (inf,sup:integer; var i:integer); begin writeln('Digita un intero compreso tra ', inf, ' e ', sup); readln(i); while (inf>i) or (i>sup) do begin writeln('====Valore fuori dall'intervallo. Digita nuovamente l'intero:'); readln(i); end; end; {Assume n strettamente positivo. Legge da terminale n interi compresi tra inf e sup, usando leggiIntero, e li memorizza in v[1..n]} procedure leggiArray(n,inf,sup:integer; var v:VettInt); var i:integer; begin for i:=1 to n do begin writeln('Elemento numero ',i,'.'); leggiIntero(inf,sup,v[i]); end end; {Questa funzione assume n strettamente positivo. Restituisce la media aritmetica (usando div per la divisione) di v[1..n].} function media(a:VettInt; n:integer;):integer; var r:integer; {Memorizza risultati intermedi} i:integer; {Contatore usato nel ciclo for} begin r:=0; for i:=1 to n do r:=r+a[i]; {r = a[1]+...+a[i]} media:= r div n; end; {Questa funzione restituisce il fattoriale di m. Se m<0 restituisce 1.} function longfatt(m:integer;):longinteger; var r:longinteger; {Memorizza risultati intermedi e risultato finale} i:integer; {Contatore usato nel ciclo while} begin i:=0; r:=1; while (m>i) do {0<=i<=max(0,m) and r=i!} begin i:=i+1; r:=r*i; end; {se m<0 allora i=0, quindi r=1. se m>=0 allora i=m, quindi r=m!.} longfatt:=r; end; begin{main} write('Questo programma calcola il fattoriale della media'); writeln(' di n interi'); leggiIntero(1,Imax,n); leggiArray(n,0,maxint,a); write('Il fattoriale della media aritmetica e`: '); writeln(longfatt(media(a,n)); end.