con Java
Lezione 0 - Introduzione alla Programmazione
ALGORITMI
ALGORITMI… MA CHE SIETE? (1)
Il termine algoritmo ha diverse definizioni:
➢ Istanza: x∈DI
➢ Soluzione: f(x)∈DS
ES - Moltiplicazione di z interi.
Come vedremo, UML farà molto di più… ma per ora restiamo con i piedi ben saldi
per terra.
DIAGRAMMI DI FLUSSO (2)
Esistono molteplici SW per la realizzazione dei flowcharts, eccone un paio:
Come potete vedere, i flowchart non sono gli unici diagrammi che questi SW
permettono di disegnare. La cosa ci tornerà utile...
DIAGRAMMI DI FLUSSO (3)
Come si legge un flowchart?
1. Parti dall’inizio.
2. Segui la freccia fino al prossimo blocco.
3. Termina se sei alla fine.
4. Esegui il contenuto del blocco raggiunto.
5. Torna a 2.
...aspettate...
DIAGRAMMI DI FLUSSO (4)
BLOCCHI ELEMENTARI:
Algoritmo molt1 (int a, int b) ⇾ int Algoritmo molt2 (int a, int b) ⇾ int
1. prodotto ⇽ 0 1. prodotto ⇽ 0
2. WHILE b>0 DO 2. WHILE b>0 DO
3. prodotto ⇽ prodotto+a 3. IF b.isDispari() THEN
4. b ⇽ b-1 4. prodotto ⇽ prodotto + a
5. RETURN prodotto 5. a⇽a+a
6. b ⇽ b/2
7. RETURN prodotto
VALUTAZIONE DEGLI ALGORITMI (3)
Contare le righe è un primo modo per valutare la complessità perché si contano le
operazioni che l’algoritmo dovrà effettuare.
molt1 esegue le righe 1,5 per 1 volta (totale 2); 3,4 per b volte (totale 2b); 2 per
b+1 volte. In totale, molt1 esegue 3b+3 righe.
molt2 esegue le righe 1,7 per 1 volta (totale 2); 3,5,6 per b volte (totale 3b); 4 per
≤b volte (al massimo b, quindi); 2 per b+1 volte. Nel peggiore dei casi, molt2
esegue 5b+3 righe. Nel migliore, 4b+1.
Direi che è evidente quale sia l’algoritmo migliore.
Provate!
VALUTAZIONE DEGLI ALGORITMI (ESERCIZI)
Valutare la complessità temporale in termini di righe degli algoritmi progettati nella
scorsa sezione. Cimentarsi nello scrivere pseudocodice se si ha tempo o se si è
in difficoltà.
TEORIA DI BASE DELL’INFORMAZIONE
LO PARLI IL BINARIO?
Il bit è l’unità di informazione di base che può assumere solo due valori: 0 e 1. A
livello elettronico essi vengono rappresentati con due range di livelli di tensione:
bassa per 0 e alta per 1. Ma a noi l’elettronica non interessa…
Sapete parlare il binario?
Lo 0 e l’1 del bit possono essere interpretati in molti modi: spento e acceso, no e
sì, falso e vero (Il Boolean è un grande amico di quest’ultima interpretazione).
Per informazioni più grandi ci vogliono più bit. In generale:
k bit identificano 2k informazioni!
TASSONOMIA DEL BIT
Il bit (b) è l’unità base di rappresentazione dell’informazione. Grandi informazioni
sono più comodamente rappresentati con multipli.
A ㄱA
0 1
1 0
AND
L’operatore AND necessita due valori di input per funzionare. Modella il costrutto logico della
congiunzione, ovvero la ”e”. Esso restituisce Vero (1) solo se entrambi gli ingressi sono Veri.
“Vado in spiaggia solo se c’è il sole e se c’è la gnocca che mi piace / il figo dietro a cui sbavo /
inserire altro”.
Controllando le tabelle della verità, si può notare che un qualsiasi valore in AND
con 0 fa 0, proprio come accade con la moltiplicazione; mentre basta un 1 per
l’OR per risultare 1.
Per questo motivo essi prendono il nome di somma logica (OR) e prodotto
logico (AND). Inoltre, proprio come nell’algebra classica le operazioni di AND
precedono quelle di OR.
MANIPOLAZIONE ALGEBRICA
Identità 1x=x 0+x=x
Inverso ㄱx x = 0 ㄱx+x = 1
● !(xy)=!x+!y
● !(x+y)=!x!y
ALGEBRA BOOLEANA (ESERCIZI)
Definire una funzione logica rappresentando con una tabella della verità e definendo quindi
un’espressione per i seguenti scenari:
A. Voglio uscire di casa solo se sono sano e non c’è un temporale; oppure se un amico ha
bisogno.
B. Posso rilassarmi se è sera o se ho già mangiato o se sono stanco. In ogni caso non posso
riposarmi se in TV c’è Baywatch.
Calcolare la tabella della verità per la seguente espressione (suggerimento: semplificate!):
!D!ABC+!DABC+!D!AB!C+!DAB!C
Date queste espressioni, definire espressioni equivalenti che usano solo l’AND:
● A+B
● AB+B(A+C)
CENNI ALL’ARCHITETTURA DEL
CALCOLATORE
Macchina di Von Neumann
COMPONENTI PRINCIPALI DELL’ELABORATORE
● CPU: Il cuore (o meglio, cervello) dell’elaborazione. Tutte le operazioni viste
fino ad ora e alcune altre vengono eseguite al suo interno. Composta da:
○ ALU: Unità aritmetico-logica che si occupa di eseguire i calcoli.
○ UC: Unità di controllo che si occupa di controllare il funzionamento della CPU.
○ Registri: Memorie interne alla CPU estremamente veloci e piccole che contengono i dati
fondamentali per l’esecuzione.
● Memoria Principale: In genera conosciuta più volgarmente con il termine
“RAM”. Contiene tutti quei dati e quelle istruzioni dei programmi eseguiti che
non possono essere contenuti nei registri. Più grandi ma più lente dei registri.
● Bus: Collegamenti tra componenti che trasportano informazioni.
● I/O: Interfacce con in mondo esterno.
● Memorie di Massa: (In realtà sono viste come dispositivi I/O) Memorie molto
grandi ma molto lente per l’archiviazione dei dati.
GERARCHIA DELLA MEMORIA
Le memorie sono intese per essere viste come disposte in una gerarchia: più alto si è
nella gerarchia più è alta la velocità di accesso; più si è in basso più cresce la grandezza.
L’idea della gerarchia è cercare di offrire la disponibilità di grandezza dei livelli inferiori ai
livelli superiori.
Il processore non può tenere tanti dati nei registri, quindi l’accesso alla memoria è
inevitabile!
CICLO FDE (1)
Il ciclo FDE è il la sequenza di operazioni che il processore deve eseguire per
ottenere le informazioni di cui ha bisogno per eseguire le istruzioni dei programmi.
CICLO FDE (2)
Il processore:
1. FETCH: Accede alla memoria e preleva l’istruzione corretta caricandola in un
registro apposito (IR).
2. DECODE: Decodifica l’istruzione prelevata per comprendere quali operazioni
deve eseguire. La UC è colei che opera la decodifica e prepara la CPU
all’esecuzione.
3. EXECUTE: L’operazione viene eseguita. Se l’istruzione decodificata indica un
prelievo di dati dalla memoria da trasferire nei registri, viene fatto un accesso
alla memoria. Se l’operazione eseguita ha risultati da mantenere, la memoria
ha bisogno di essere acceduta e l’informazione deve essere lì scritta.
COME SI ACCEDE ALLA MEMORIA?
L’accesso alla memoria è indicizzato: la memoria
principale è divisa in indirizzi contenenti un certo numero
di “parole”. Le parole sono sequenze di un certo numero
di bit la cui grandezza dipende dal SO in uso.
Per evitare di dover scrivere più e più volte lo stesso codice è stato introdotto il
concetto di funzione (aka: metodi in C# e Java): frammenti di codice invocabili per
nome che accettano un certo numero di argomenti (ingressi) e che lavorano a
partire da essi per effettuare operazioni e, spesso, restituire un risultato.
Per rappresentare tipi di dato non base, composti da aggregazioni di altri tipi, sono
state introdotte le strutture dati: dati contigui in memoria di tipi diversi
interpretabili come un insieme per definire un’entità.
ESEMPIO DI STRUTTURA IN C
ALLOCAZIONE IN MEMORIA ESPLICITA
I linguaggi di programmazione orientati alle funzioni hanno spesso una gestione della
memoria esplicita.
Mentre tipi di dato base sono allocati in memoria staticamente al momento della
dichiarazione della variabile, tipi di dato non base hanno bisogno di un indirizzo per
essere individuate in memoria poiché vengono allocati dinamicamente.
Quando si crea una variabile di tipo non base, bisogna prima allocare spazio in memoria
strutturato adeguatamente per contenere i dati di tale variabile. Può essere fatto
staticamente, così che lo spazio viene dedicato in compilazione, che dinamicamente
tramite l’operazione di malloc.
PUNTATORI
I puntatori sono tipi speciali che vengono spesso trattati come interi nei linguaggi
di programmazione orientati alle funzioni. Essi rappresentano un indirizzo in
memoria e sono utilizzati per accedervi.
Ma preparatevi all’incubo…