Programmazione
Valerio Perticone, Sergio Perticone
Programmazione
•
La programmazione è un processo che parte
dall'analisi di un problema computazionale ed
arriva, mediante un'opportuna codifica formale, alla
creazione di un programma (software)
•
Ma che significa computazionale?
Computazione
•
Analizziamo una comune definizione matematica:
•
Radice quadrata di x
•
La radice quadrata di x è quel numero y che
moltiplicato per sé stesso è uguale ad x
•
Questa definizione è esauriente per comprendere il
significato di radice quadrata
•
Ma non fornisce informazioni su come calcolarla!
Conoscenza
•
La definizione precedenza è un esempio di
conoscenza proposizionale
•
A noi interessa conoscere un algoritmo che ci
permetta in pratica di risolvere il nostro problema
(calcolare la radice quadrata)
•
Erone di Alessandria (I secolo d.C.) ha descritto
una procedura per calcolarlo, che costituisce uno
di primi esempi di algoritmo (conoscenza
procedurale)
Algoritmo di Erone
•
Passo 1: Fissa una soglia t ad un valore arbitrariamente basso
•
Passo 2: Scegli un valore arbitrario y
•
Passo 3: Poni d uguale alla differenza in valore assoluto tra y²
ex
•
Passo 4: Se tale d è inferiore a t, allora y è la soluzione quindi
termina
•
Passo 5: Altrimenti, sostituisci y con la media tra y e x/y
•
Passo 6: Vai al punto 3
Domanda
•
Quello descritto è un programma?
•
No, benché sia una procedura, non c’è alcuna
forma di codifica formale dell’algoritmo
Codifica
•
Il concetto di codifica è strettamente collegato ai
protocolli di comunicazione
•
Quando comunichiamo seguiamo istintivamente
alcune regole implicite che sono note nella società
in cui ci troviamo (una forma di “galateo”)
•
Esempio: la stretta di mano è un gesto
comunemente associato al saluto (ma assume
significato di lealtà sportiva in seguito ad una
partita)
Codifica
•
Con l’evoluzione della scrittura e del linguaggio,
oggi associamo particolari segni o suoni a
significati che sono molto lontani dall’oggetto
•
Esempio: SOS nel codice Morse
Codifica
•
Nel linguaggio matematico il concetto di codifica è
più rigoroso e richiede che non siano presenti
ambiguità
•
La definizione formale di codifica si associa al
concetto matematico di funzione
•
In particolare sono richieste funzioni iniettive
Linguaggi di
programmazione
•
Un linguaggio di programmazione è un linguaggio
utilizzato per il controllo di una macchina
•
Il programmatore codifica le istruzioni da compiere
utilizzando il linguaggio della macchina
•
Una macchina può essere un computer, uno
smartphone, una lavatrice, …
Un po’ di storia
•
•
Prima dell’invenzione del computer sono stati definiti
linguaggi di programmazione arcaici per esprimere in
maniera rigorosa il processo di calcolo
•
Characteristica universalis (Gottfried Leibniz, 1666)
•
Macchina analitica di Babbage (Ada Lovelace, 1843)
•
Lambda calcolo (Alonzo Church, 1936)
•
Macchina di Turing (Alan Turing, 1936)
Sono tutti precedenti all’invenzione del computer!
Linguaggi di
programmazione
•
Oggi esistono numerosi linguaggi di programmazione,
dotati di alcune peculiarità e specializzazioni nell’ambito di
applicazione
•
Esempi:
•
Java
•
MATLAB
•
R
•
Python
Caratteristiche comuni
•
Istruzioni
•
Variabili
•
Operatori aritmetici e logici
•
Strutture per il controllo del flusso
•
Procedure
Istruzioni
•
Un programma è descritto da un codice sorgente (o
semplicemente sorgente). Il sorgente è composto da un numero
finito di istruzioni disposte su righe separate
istruzione 1
istruzione 2 // commento
...
istruzione n
•
Il flusso del programma è dato dalla sequenza di istruzioni eseguite
•
Se non specificato diversamente, l’esecuzione avviene nell’ordine
in cui compaiono le istruzioni
•
È possibile aggiungere commenti per specificare il significato delle
istruzioni. I commenti non sono interpretati dalla macchina.
Variabili
•
Le variabili possono essere considerate come scatole
etichettate il cui contenuto può essere modificato o
osservato quando necessario
•
Regole:
•
ogni variabile va dichiarata prima di essere utilizzata
•
ogni variabile ha un nome univoco
•
ogni variabile ha associato un tipo
Pseudocodice
•
Per presentare algoritmi spesso si utilizza lo
pseudocodice
•
Corrisponde ad un linguaggio di programmazione
inventato e non veramente implementato, ma
sufficientemente formale
•
In questo caso s’ignorano, ove possibile, tipi e
dichiarazioni di variabili
Assegnamento
•
Per assegnare un valore ad una variabile di nome
x, useremo l’operatore di assegnamento =
x = 42
x = 10
y = 4
// la variabile x adesso conterrà il valore intero 42
// adesso x contiene 10
// la variabile y contiene 4
Operatori aritmetici
•
•
Possiamo manipolare le variabili numeriche utilizzando le comuni
operazioni aritmetiche:
•
+ (addizione)
•
- (sottrazione)
•
* (prodotto)
•
/ (divisione)
Tali operatori possono essere combinati in maniera non binaria:
area = base * altezza
perimetro = base*2 + altezza*2
// esempio binario
Operatori unari
•
Esistono operatori unari, ovvero che operano su un solo operando
•
- (segno meno)
•
++ (incremento)
•
-- (decremento)
x = 3
x++
x-x = x + 1
// x è uguale a 4
// x è uguale a 3
// è equivalente a x++
y = 5
z = -y
w = -z
// z è uguale a -5
// w è uguale a 5
Operatori logici
•
Gli operatori logici valutano un predicato e producono una costante
logica booleana che corrisponde al suo valore di verità (Vero o Falso)
•
Sono comunemente indicati con true o false
•
Un tipo di predicato sono, ad esempio, le relazioni d’ordine:
•
< (strettamente minore)
•
<= (minore o uguale)
•
> (strettamente maggiore)
•
>= (maggiore o uguale)
Operatori logici
•
Esempi:
p = 42 > 1
q = 21 < 21
m = 21 <= 21
// p sarà uguale a true
// q sarà uguale a false
// m sarà uguale a true
•
Esistono inoltre gli operatori di eguaglianza:
•
== (uguale)
•
<> (non uguale)
•
Esempi:
p
q
m
n
=
=
=
=
(10 == 10)
(12 <> 10)
(12 <> 12)
(p == q)
//
//
//
//
p
q
m
n
sarà
sarà
sarà
sarà
uguale
uguale
uguale
uguale
a
a
a
a
true
true
false
true
Operatori logici
•
Gli operatori di confronto sono binari e ammettono
solamente operandi che possono essere messi in
relazione tra loro
p = (10 == 10 == 11)
q = (23 <= true)
// errore
// errore
Connettivi logici
•
Oltre alle operazioni di eguaglianza, è possibile
effettuare altre operazioni con i valori di verità
•
Le seguenti operazioni sono detti connettivi logici:
•
&& (congiunzione logica: and)
•
|| (disgiunzione logica: or)
•
! (negazione logica: not)
Tabella di verità
Congiunzione logica
(AND)
&&
Disgiunzione logica
(OR)
||
FALSE
FALSE
FALSE
FALSE
FALSE
FALSE
FALSE
TRUE
FALSE
FALSE
TRUE
TRUE
TRUE
FALSE
FALSE
TRUE
FALSE
TRUE
TRUE
TRUE
TRUE
TRUE
TRUE
TRUE
Connettivi logici
•
Esempi:
x
p
q
m
n
=
=
=
=
=
5
(10 < x) || (2 < x)
(x > 1) && (x == 3)
!(x == 5)
true || false
//
//
//
//
p
p
m
n
sarà
sarà
sarà
sarà
uguale
uguale
uguale
uguale
a
a
a
a
true
false
false
true
Precedenza degli operatori
•
•
Come per la matematica, esistono regole per determinare la
precedenza degli operatori. Vale la seguente scala di priorità (in
ordine di precedenza):
•
* /
•
+ -
•
== <> < <= > >=
•
&&
•
||
Gli operatori binari allo stesso livello seguono la regola associativa
da sinistra verso destra. Nel dubbio si utilizzano le parentesi.
a = x / y * z
b = x / (y * z)
// a e b sono diversi!
Variabili non scalari
•
Quando trattiamo quantità numeriche abbiamo a
che fare con variabili scalari
•
In programmazione sono spesso necessarie
grandezze non scalari, ovvero non direttamente
rappresentabili tramite un numero
•
Un esempio classico è il vettore (o array)
•
L’array è un esempio di struttura dati
Array
•
L’array è una sorta di contenitore dotato di un
numero finito di cellette ordinate
•
Per accedere ad una cella (slot) si utilizza un indice
numerico intero
•
Gli indici partono solitamente da 0 (ovvero la prima
cella dell’array è indicata dal numero 0)
Array
v = [2, 4, 6, 8]
x = v[0]
y = v[3]
z = v[4]
v[2] = 0
//
//
//
//
//
inizializzo con i valori tra parentesi quadre
x conterrà 2
y conterrà 8
errore: indice fuori dai limiti
l'array adesso sarà: [2, 4, 0, 8]
2 4 0 8
Record
•
Un altro tipo di variabile non scalare è il record
•
Un record può contenere valori relativi ad un’entità
•
Un record è composto da campi (fields)
•
Si accede ai vari campi utilizzando la notazione
punto (variabile.campo)
Record
•
Supponiamo di voler creare un record che
rappresenta una persona fisica
•
Questo record conterrà i campi “nome” ed “età”
p = {nome: "Mario", età: 35}
x = p.età
n = p.nome
p.età++
p.nome = "Luigi"
//
//
//
//
//
salva in p i dati relativi a Mario
salva in x l'età (35)
salva in n il nome ("Mario")
p è {nome: "Mario", età: 36}
Mario è diventato Luigi
Controllo del flusso
•
Nella forma più semplice, il flusso di un programma
segue le istruzioni riga per riga
•
Spesso è necessario modificare l’ordine di esecuzione
delle istruzioni nel caso di algoritmi più elaborati
•
Esistono diversi costrutti per il controllo del flusso, ma
quelli fondamentali sono di due tipi:
•
alternativa
•
iterazione
Alternativa
•
Usando il costrutto alternativa possiamo eseguire
blocchi di codice in base al verificarsi di una
condizione logica
// semplice
if (predicato) {
blocco di istruzioni
}
// alternativa con else
if (predicato) {
blocco se predicato vero
} else {
blocco se predicato falso
}
•
Ne esistono due tipi:
•
Nello pseudocodice le graffe delimitano le istruzioni
appartenenti al blocco
Alternativa
•
Esempi
if x == 42 {
y = 2
} else {
y = 10
}
// questa istruzione verrà eseguita se x è 42
// altrimenti, il codice eseguito sarà questo
if (x < 10) || (z == 2) {
y = 2
z = 18
}
Iterazione
•
Il costrutto iterazione permettere di ripetere più volte un
certo blocco di codice fintantoché il predicato è vero
•
La ripetizione viene anche chiamata ciclo (o loop)
while (predicato) {
blocco
}
•
Il predicato viene anche chiamato condizione: il suo valore
di verità è controllato una volta sola precedentemente
all’esecuzione della prima istruzione del blocco
Iterazione
v = [ 1, 2, 3, 4, 5, 6, 7, 8 ]
n = 8 // lunghezza array
i = 0
while i < n {
v[i] = v[i] * 2
i++
}
•
Quale sarà il contenuto di v al termine del ciclo?
Iterazione
•
Spesso nei programmi si utilizza, per questioni
pratiche, un ciclo “infinito”
•
Basta utilizzare come predicato la costante true
introdotta in precedenza
while true {
// ciclo infinito
}
•
Per interrompere l’esecuzione del ciclo si utilizza
l’istruzione break
break
•
Supponiamo di dover scrivere un videogioco in cui è
presente un numero finito di vite e il gioco termina una
volta esaurite le vite
•
Lo pseudocodice avrà questa forma:
numeroVite = 3
while true {
// codice che gestisce il gioco
if numeroVite == 0 {
break
}
// codice che gestisce i controlli
}
// codice che mostra game over e termina la partita
Procedure
•
Le procedure (o funzioni) permettono di richiamare
blocchi di codice in determinati punti dello stesso
programma o di programmi diversi
•
Molte procedure sono fornite dai creatori del
linguaggio di programmazione o da altri
sviluppatori sotto forma di librerie (raccolte di
procedure)
•
Alcune procedure restituiscono un valore come
risultato
Esempi di procedure
// assegna ad y il risultato della funzione sqrt applicata a 9
y = sqrt(9)
// assegna ad un valore casuale compreso tra 1 e 10
x = random(1, 10)
if y == 3 {
print(x)
} else {
abort()
}
// stampa a schermo il valore di x
// termina il programma in maniera anomala
Procedure
•
La dichiarazione di una procedura è caratterizzata da una
parola chiave che ne precede il nome, dal nome della
procedura e dai parametri in ingresso della procedura,
racchiusi tra parentesi tonde
•
Nello pseudocodice useremo la parola chiave func
// dichiarazione:
func somma3(a, b, c) {
return a + b + c
}
// utilizzo:
x = somma3(2, 4, 8)
// x conterrà 14
Procedure
func abs(a) {
if a < 0 {
return -a
}
return a
}
•
Che funzione matematica calcola questa
procedura?
Algoritmo di Erone
// definizione
func sqrt(x) {
t = 0.001
y = random(1, x)
while true {
d = abs(y*y - x)
if d < t {
return y
}
y = (y + x/y) / 2
}
}
// esempio d'uso
y = sqrt(9)
// media tra y e x/y