Il 0% ha trovato utile questo documento (0 voti)
17 visualizzazioni68 pagine

Appunti Di Informatica

Caricato da

Emanuele Fraiese
Copyright
© © All Rights Reserved
Per noi i diritti sui contenuti sono una cosa seria. Se sospetti che questo contenuto sia tuo, rivendicalo qui.
Formati disponibili
Scarica in formato ODT, PDF, TXT o leggi online su Scribd
Il 0% ha trovato utile questo documento (0 voti)
17 visualizzazioni68 pagine

Appunti Di Informatica

Caricato da

Emanuele Fraiese
Copyright
© © All Rights Reserved
Per noi i diritti sui contenuti sono una cosa seria. Se sospetti che questo contenuto sia tuo, rivendicalo qui.
Formati disponibili
Scarica in formato ODT, PDF, TXT o leggi online su Scribd
Sei sulla pagina 1/ 68

APPUNTI DI

INFORMATIC
A
MODELLI E PYTHON
COMANDI DI PYTHON
# rappresenta un commento e non sono enunciati: servono a
fornire informazioni ai programmatori;
stringa: è una sequenza di caratteri racchiusa da una coppia di
virgolette, singole o doppie (‘ ‘ “”);
print() ci permette di visualizzare un valore;
funzione: è un insieme di istruzioni di programmazione che
servono a portare a termine un compito specifico;
pseudocodice: una descrizione informale di una sequenza di passi
che portano alla soluzione di un problema;
variabile: è una zona di memoria, dotata di un nome, in cui si
possono archiviare informazioni;
enunciato di assegnazione: memorizza un valore in una
variabile;
Numeri in Python: int, sono tutti i numeri interi sia positivi che
negativi, 0 è un numero intero;
float, sono tutti i numeri frazionari, in notazione esponenziale, con
esponente negativo o positivo;
costanti: si usano per quei valori che non sono soggetti a
modifiche durante l’esecuzione del programma (di solito si usa un
nome composto da sole lettere maiuscole);
% restituisce il resto;
// divisione intera, ignorando il resto;
** elevazione a potenza;
/ divisione;
-sottrazione;
+ addizione;
* moltiplicazione;

FUNZIONI MATEMATICHE
Per poter usare, in un programma, una funzione della libreria, è
necessario importarla: ‘from math import’:
abs(x) il valore assoluto di x;
round(x,n) il valore x in virgola mobile arrotondato in modo che sia
un numero intero o che abbia n cifre decimali
max(x1,x2,x3,…,xn) il valore maggiore tra quelli presenti come
argomenti;
min(x1,x2,x2,x3,…,xn) il valore minore tra quelli presenti come
argomenti;
sqrt(x) la radice quadrata di x (con x >=0);
trunc(x) tronca il valore x in virgola mobile, restituendo un
numero intero;
cos(x) il coseno di x, in radianti;
sin(x) il seno di x, in radianti;
tan(x) la tangente di x, in radianti;
exp(x) e^x;
degrees(x) converte x da radianti a gradi;
radians(x) converte x da gradi in radianti;
log(x) oppure log(x,base) il logaritmo naturale di x (cioè
logaritmo in base e) oppure il logaritmo di x nella base indicata;
STRINGHE
len() restituisce il numero di caratteri presenti in una stringa;
int e float convertono una stringa contenente un numero in tale
valore numerico;
stringa[n] restituisce il carattere nella posizione n della stringa;
s.lower la versione minuscola della stringa s ;
s.upper la versione maiuscola della stringa s ;
s.replace(old,new) una nuova versione della stringa s nella quale
ogni occorrenza della sottostringa old è stata sostituita con new;
input() serve per leggere dati forniti in ingresso mediante la
tastiera
chr(numero) restituisce il carattere corrispondente al numero nella
tabella UNICODE
ord(carattere) restituisce il numero corrispondente al carattere
nella tabella UNICODE
s.find(str) calcola la prima posizione di s in cui compare la
stringa str. Se la stringa str non compare in s restituisce -1
s.rfind(str) calcola la prima posizione di s in cui compare la
stringa str partendo dalla fine della stringa s. Se la stringa str non
compare in s restituisce -1
s.count(str) calcola quante volte str compare in s
OPERATORE DI FORMATO PER STRINGHE
“%d” si usa d per i numeri interi
“%5d” vengono aggiunti spazi in modo che l’ampiezza del campo sia
uguale a 5
“&05d” inserendo uno 0 prima dell’ampiezza del campo, vengono
aggiunti zeri al posto degli spazi
“Quality:%5d” i caratteri che si trovano nella stringa ma sono al di
fuori di un indicatore di formato vengono visualizzati normalmente
“%f” si usa f per i numeri in virgola mobile
“%.2f” visualizza due cifre dopo il punto decimale
“%7.2f” vengono aggiunti spazi in modo che l’ampiezza del campo
sia uguale a 7
“%s” si usa s per le stringhe
“%d %.2f” si può imporre il formato desiderato a più valori
“%9s” le stringhe vengono allineate a destra, in mancanza di
indicazione diversa
“%-9s” per allineare a sinistra si usa un carattere –
“%d%%” per visualizzare un segno di percentuale si usa %%

L’ENUNCIATO if
if consente ad un programma di compiere azioni diverse in
relazione alla natura dei dati che vengono elaborati; il carattere due
punti posto dopo una condizione identifica un enunciato composto.

OPERAZIONI RELAZIONALI
> maggiore
>= maggiore o uguale
> minore
<= minore o uguale
== uguale
!= diverso
+= alterna i caratteri di due stringhe

DIRAMAZIONI ANNIDATE
Quando un enunciato di decisione è contenuto nel ramo di un altro
enunciato di decisione, si dice che i due enunciati sono annidati ; le
decisioni annidate servono per risolvere problemi che richiedono
decisioni su più livelli.

DIAGRAMMI DI FLUSSO
I diagrammi di flusso sono costituiti da elementi che rappresentano
compiti da svolgere, acquisizioni e visualizzazione di dati e decisioni
da prendere; ogni ramo di una decisione può contenere compiti da
svolgere e altre decisioni da prendere; non far mai entrare una
freccia all’interno di una diversa diramazione.

VARIABILI BOOLEANE E OPERATORI


Il tipo booleano, bool, ha due valori: False e True;

Python ha due operatori booleani che combinano condizioni: and e


or.

A B A and B A
not A
True True True True
False
True False False False
True
False True False
False False False Per
invertire una condizione si usa l’operatore not.

A B A or B
True True True
True False True
False True True
False False False

ANALISI DI STRINGHE
sottostriga in s restituisce True se la stringa s contiene
sottostringa, altrimenti False
s.count(sottostringa) restituisce il numero di ricorrenze non
sovrapposte di sottostringa nella stringa s
s.endswith(sottostringa) restituisce True se la stringa s
termina con sottostringa, altrimenti False
s.find(sottostringa) restituisce il più basso valore dell’indice
nella stringa s dove inizia una occorrenza sottostringa, oppure -1 se
sottostringa non ricorre in s
s.startswith(sottostringa) restituisce True se la stringa s
inizia con sottostringa, altrimenti False
s.isalnum restituisce True se la stringa s è costituita da sole
lettere o cifre e contiene almeno un carattere, altrimenti False
s.isalpha restituisce True se la stringa s è costituita da sole
lettere e contiene almeno un carattere, altrimenti False
s.isdigit restituisce True se la stringa s è costituita da sole cifre
e contiene almeno un carattere, altrimenti False
s.islower restituisce True se la stringa s contiene almeno una
lettera e tutte le lettere della stringa sono minuscole, altrimenti
False

CICLO While
Un enunciato while esegue ripetutamente istruzioni, finché una
specifica condizione è vera.

CICLO for
Il ciclo for viene usato per eseguire iterativamente istruzioni sugli
elementi di un contenitore (stringa, liste, ecc...)
range scandisce ogni singola lettera della stringa

FUNZIONI
Una funzione è una sequenza di istruzioni a cui viene dato un nome;
quando una funzione viene invocata, le vengono forniti i suoi
argomenti; il valore restituito è il risultato che ha calcolato. Essa si
introduce con def e il suo valore con return.

Esempio di funzioni in Python


def <nome funzione> (<parametri formali>):
istruzioni
..........
return <valore>

LISTE
[] crea una nuova lista vuota o contenente inizialmente gli
elementi forniti
[elem1,elem2,elem3,....]

l[from:to] crea una lista contenente una sottosequenza degli


elementi della lista l, a partire dalla posizione from e proseguendo
fino alla posizione to, esclusa;

l[1]='casa' sostituisce un elemento della lista con l'elemento


dato;

len(l) restituisce il numero di elementi di una lista

list(sequenza) crea una lista contenente tutti gli elementi della


sequenza;

values*num crea una lista replicando num volte gli elementi della
lista values;

values+morevalues crea una lista concatenando gli elementi delle


due liste;
sum(l) calcola la somma dei valori contenuti nella lista l;

min(l) restituisce il valore minimo o massimo nella lista l


max(l)

l1==l2 verifica se le due liste contendono gli stessi elementi;

l.pop() elimina dalla lista l'ultimo elemento oppure l'elemento che


si trova nella posizione indicata. Tutti gli elementi che seguono la
posizione indicata vengono spostati all'indietro di un posto
l.pop(posizione)
l.insert(posizione,elemento) inserisce nella lista l'elemento
nella posizione indicata. Tutti gli elementi che seguono la posizione
indicata vengono spostati in avanti di un posto;

l.append(elemento) aggiunge l'elemento alla fine della lista;

l.index(elemento) restituisce la posizione dell'elemento nella


lista;

l.remove(elemento) elimina dalla lista l'elemento indicato e sposta


all'indietro di un posto tutti gli elementi che lo
seguono;

l.sort() ordina gli elementi della lista in senso crescente;

l.count(elemento) conta quante volte compare l'elemento nella


lista;

extend(lista) aggiunge alla lista una nuova lista;

reverse() rovescia la lista, mettendo gli elementi in ordine inverso;

APRIRE UN FILE
Per aprire un file, occorre fornire il suo nome, oltre alla modalità di
apertura;
infile = open(“input.txt”, “r”) per la lettura
outfille = open(“output.txt”, “w”) per la scrittura

Dopo aver elaborato un file, bisogna chiuderlo;


infile.close()
outfile.close()

Per leggere una riga di testo da un file si usa il metodo readline;


line = infile.readline()

s=f.read trasforma tutto il file in una stringa;

Per scrivere in un file si una il metodo write o la funzione print;


outfile.write(“Hello, World!\n”)

Per leggere le righe di testo da un file, si può usare un ciclo for che
operi sull'oggetto di tipo file
for line in infile:
print(line)

Per eliminare il carattere newline alla fine di una stringa si può


usare il metodo rstrip
line = line.rstrip()

s.lstrip() vengono eliminate i caratteri di spaziatura all'inizio

s.lstrip(caratteri) vengono eliminati i caratteri all'inizio

s.rstrip() vengono eliminate i caratteri di spaziatura alla fine

s.rstrip(caratteri) vengono eliminati i caratteri alla fine

s.strip() elimina sia a destra che sinistra i caratteri di spaziatura

s.strip(caratteri) elimina sia a destra che sinistra i caratteri

Il metodo split suddivide una stringa nelle sue singole parole


s.split(' ')
INSIEMI
Un insieme memorizza una raccolta di valori univoci, cioè non
contiene duplicati, si crea usando un insieme letterale o la funzione
set.
Cast = {“Luigi”, “Gumbys”, “Spini”}

Names=[“Luigi”, “Gumbys”, “Spini”]


cast= set(names)

Con il metodo add si può aggiungere un nuovo elemento a un


insieme
cast = set([“Luigi”, “Gumbys”, “Spini”])
cast.add(“Arthur”)

Con il metodo discard si può eliminare un elemento da un insieme


cast.discard(“Arthur”)

Il metodo union genera un nuovo insieme che contiene gli elementi


presenti in almeno uno dei due elementi
inEither = british.union(italian)

Il metodo intersection genera un nuovo insieme che contiene gli


elementi presenti in entrambi gli insiemi
inBoth = british.intersection(italian)

Il metodo difference genera un nuovo insieme che contiene gli


elementi presenti nel primo insieme ma non nel secondo
DIZIONARI
I dizionari contengono coppie chiave/valore
favoriteColors = {“Romeo”: “Green”, “Adam”: “Red”}

In un dizionario, per accedere al valore associato a una chiave si


usa l'operatore [].
Per verificare se una chiave è presente in un dizionario si usa
l'operatore in; usando l'operatore [] si posso aggiungere nuove
coppie oppure le si possono modificare;
contacts[“John”] = 4578102

Per eliminare una coppia da un dizionario si usa il metodo pop


contacts.pop(“Fred”)

d = dict() crea un dizionario vuoto o contenente una copia del


dizionario c
d = dict(c)

d = {} crea un nuovo dizionario vuoto o contenente inizialmente le


coppie specifiche, ognuna delle quali è costituita da una chiave k e
un valore v, separati da un carattere “due punti”.

len(d) restituisce il numero di coppie presenti nel dizionario d

repr fornisce un mezzo per produrre rappresentazioni di oggetti


con limiti imposti sulla dimensione delle stringhe risultanti.

chiave in d determina se la chiave appartiene o non appartiene al


dizionario d
chiave not in d

d[chiave] = valore aggiunge una nuova chiave/valore al


dizionario d, se chiave non vi è già presente, altrimenti modifica il
valore associato alla chiave.
x = d[chiave] restituisce il valore associato alla chiave data, che
deve essere presente nel dizionario d, altrimenti viene sollevata
un'eccezione;

d.get(chiave, predefinito) restituisce il valore alla chiave data,


oppure il valore predefinito se la chiave non è presente nel
dizionario d;

d.pop(chiave) elimina dal dizionario d la chiave e il valore ad essa


associato; se la chiave non è presente nel dizionario, solleva
un'eccezione;

d.values() restituisce una sequenza contenente tutti i valori


presenti nel dizionario.

d[oggetto][0] restituisce il primo valore della chiave


d[oggetto][1] restituisce il secondo valore della chiave

ESPRESSIONI REGOLARI
Prima di tutto bisogna importare le funzioni attraverso import re

re.search('Mario', elenco) cerca la stringa 'Mario' nella


stringa elenco

[a-zA-Z0-9 ] un carattere qualsiasi fra lettere minuscole,


maiuscole, cifre e lo spazio

* ripetizione (va messa praticamente sempre, a meno che non


si voglia avere un carattere solo)

[^-] carattere qualsiasi tranne –

m = re.search('(Mario) ([A-Za-z]*) ([0-9]*)', elenco) si


può usare group(n) invece di group() per trovare una parte
degli insiemi di m
m.group(1)=(Mario)
m.group(2)=([A-Za-z]*)
invece m.group() è tutto, uguale a m.group(0)
re.finditer ritorna un iteratore, si può usare in un ciclo a ogni
passo è come se fosse stato
fatto re.search

nomi che iniziano con M


i = re.finditer('(M[a-z]*) ([A-Za-z]*) ([0-9]*)', elenco)
si usa M[a-z]*

per ricercare una data [0-9][0-9]/[0-9][0-9]/[0-9][0-9][0-9]


[0-9]
due cifre, barra, due cifre, barra, quattro cifre (ma non accetta la
data 3/1/2012)
[0-9]*/[0-9]*/[0-9][0-9][0-9][0-9] accetta 3/1/2012 ma
anche 100/4/1000

* lunghezza qualsiasi
+ lunghezza maggiore o uguale a uno
{1,3} lunghezza da uno a tre

[0-9]{1,2}/[0-9]{1,2}/[0-9]{4,4}
[0-9]{1,2} = una o due cifre
[0-9]{4,4} = quattro cifre
{4,4} si può anche scrivere {4}

espressione regolare:

'[A-Z]{3} [A-Z]{3} [0-9]{2}[A-Z][0-9]{2} [A-Z][0-9]{3}[A-


Z]'

 tre maiuscole
 spazio
 tre maiuscole
 spazio
 due cifre, una maiuscola, due cifre
 spazio
 maiuscola, tre cifre, maiuscola

[ ]{0,1} spazio opzionale


{0,1} è uguale a ?
gennaio|febbraio|marzo|aprile alternative tra stringhe intere,
accetta solo le stringhe date

[0-9]{1,2} (gennaio|febbraio|marzo|aprile|maggio|giugno|
luglio|agosto|settembre|ottobre|novembre|dicembre) [0-9]
{4} scrive una data con il nome dei mesi

[0-9]*|[a-z]* una sequenza di sole cifre oppure una sequenza di


sole minuscole

{n,m} ripetizioni

. viene definito un carattere qualsiasi

re.DOTALL fa includere il ritorno a capo


codice=.{10} sequenza codice= seguita da dieci caratteri
qualsiasi
-?[0-9]+ numero intero, con segno meno opzionale

re.IGNORECASE non fa distinzione tra maiuscole e minuscole

re.search('Mario', elenco) trova Mario in posizione qualsiasi


re.search('^Mario', elenco) trova Mario solo se è all'inizio
re.search('$Mario', elenco) trova Mario solo se è alla fine

re.split divide una stringa in parti, l'espressione regolare dice


dove separare
es: [;|] dice che ; e | fungono da separatori
print(re.split('[;|]','abcd;efgh|wsl'))
stampa:
['abcd', 'efgh', 'wsl']

re.sub rimpiazza le sottostringhe che collimano con l'espressione


regolare print(re.sub('(Giorgio|Luca|Alberto)','Gianni',
"Questo l'ha fatto Giorgio, questo Alberto, questo
Luca"))
stampa:
Questo l'ha fatto Gianni, questo Gianni, questo Gianni

collimano() la semantica è una funzione matematica


data una espressione regolare e:

 collimano(e) = insieme di stringhe che collimano con


l'espressione regolare
 collimano(abc?) = {ab, abc}

 collimano(ab?|c*) = {a, ab, ∅, c, cc, ccc, … }


 collimano(a*b) = {b, ab, aab, aaab, … }

 …

ESPRESSIONI REGOLARI IN PYTHON

import re

 testo completo dei Malavoglia.


 In alternativa per ricerche più piccole 'IMalavoglia_50.txt'
(prime 50 righe)
file = 'IMalavoglia.txt'
file2 = 'IMalavoglia_50.txt'

 Espressione regolare da cercare. In Python il carattere \ va


scritto \\
esprReg = '[0-9]{1,2} (gennaio|febbraio|marzo|aprile|
maggio|giugno|luglio|agosto|settembre|ottobre|novembre|
dicembre) [0-9]{4}'
 Leggo tutto il file e lo salvo nella variabile testo
testo = open(file,encoding='UTF-8').read()
testo2 = open(file2,encoding='UTF-8').read()

 Trovo tutte le stringhe che collimano con l'espressione


regolare
 Ignoro la differenza tra maiuscole e minuscole
ris = re.finditer(esprReg,testo,re.IGNORECASE)

 Stampo espressione regolare e tutti i match con un contatore


print('Espressione Regolare:',repr(esprReg))
i = 1
for m in ris:
print(i,':',m.group())
i = i + 1

 Altre espressioni regolari da cercare:


 Coppie di parole consecutive che iniziano con la stessa lettera
esprReg2 = '[^a-z]([a-z])[a-z]*[^a-z\n]+\\1[a-z]*[^a-z\
n]'

ris = re.finditer(esprReg2,testo2,re.IGNORECASE)

 Stampo espressione regolare e tutti i match con un contatore


print('Espressione Regolare:',repr(esprReg2))
i = 1
for m in ris:
print(i,':',m.group())
i = i + 1

 Sequenza di tre parole consecutive che iniziano con la stessa


lettera
esprReg3 = '[^a-z]([a-z])[a-z]*[^a-z\n]+(\\1[a-z]*[^a-z\
n]+){2}'
ris = re.finditer(esprReg3,testo,re.IGNORECASE)

 Stampo espressione regolare e tutti i match con un contatore


print('Espressione Regolare:',repr(esprReg3))
i = 1
for m in ris:
print(i,':',m.group())
i = i + 1

 Parole che iniziano e finiscono con la stessa lettera


esprReg4 = '[^a-z]([a-z])[a-z]*\\1[^a-z]'

ris = re.finditer(esprReg4,testo2,re.IGNORECASE)

 Stampo tutti i match con un contatore


print('Espressione Regolare:',repr(esprReg4))
i = 1
for m in ris:
print(i,':',m.group())
i = i + 1

 Parole che contengono tre doppie


esprReg5 = '[^a-z][a-z]*([a-z])\\1[a-z]*([a-z])\\2[a-
z]*([a-z])\\3[a-z]*[^a-z]'

 calcolo tutti i match con la findall. Restituisce solo i caratteri


che
 corrispondono ai gruppi
ris = re.findall(esprReg5,testo2,re.IGNORECASE)

 Stampo tutti i cartatteri


print('Espressione Regolare:',repr(esprReg5))
print('Numero di stringhe trovate', len(ris), 'caratteri
corrispondenti', ris)
MATRICI
 per creare una lista di liste tutte della stessa lunghezza
l4 = [[0]*4]*4
print('\nl4=',l4)

l4= [[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0,


0]]

 in alternativa per creare una lista di liste tutte della stessa


lunghezza
l5 = [[0 for i in range(3)] for i in range(4)]
print('\nl5=',l5)

l5= [[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]

 in alternativa usando due parametri


m=4 righe
n=3 colonne
l6 = [[0 for i in range(n)] for i in range(m)]
print('\nl6=',l6)

l6= [[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]

len(l6) righe
len(l6[0]) colonne

 accesso e modifica degli elementi


 creo una matrice di dimensione mxn [0..m-1][0..n-1] con
m==n
 con numeri progressivi per riga

m = n = 4 fisso la dimensione della matrice quadrata

mat = [[i+(j*n) for i in range(n)] for j in range(m)]


print(mat)

[[0, 1, 2, 3], [4, 5, 6, 7], [8, 9, 10, 11], [12, 13, 14,
15]]

 Per accedere all'elemento nella riga 2 colonna 3


print('mat[2][3]=', mat[2][3])

mat[2][3]= 11

# Per accedere ad una riga


print('mat[1] =',mat[1])
mat[1] = [4, 5, 6, 7]

 Non si può immediatamente estrarre una colonna


 serve del codice come questo che estrae la colonna 1
col = []
for i in range(n):
col.append(mat[i][1])
print('col[1]=',col)

col[1]= [1, 5, 9, 13]

 Per stampare l'intera matrice servono 2 cicli for


for i in range(len(mat)):
for j in range(len(mat[0])):
print(mat[i][j], end = ' ') stampa la riga
separando con spazio
print() vado a riga nuova prima di
stampare la nuova riga

0 1 2 3
4 5 6 7
8 9 10 11
12 13 14 15

 Funzione che legge un file che contiene una matrice di numeri


interi nel formato
2 righe 3 colonne
234
5 -2 9
 Dove la prima riga contiene le dimensioni, numero di righe e
numero di colonne
 Le altre righe contengono i numeri per riga

def leggiMatriceFile(file):
f = open(file, 'r', encoding = 'UTF-8')
mat = [] inizializzo la matrice
dim = f.readline().split() leggo le dimensioni
righe = int(dim[0])
colonne = int(dim[1])
for i in range(righe):
riga = f.readline().split() leggo una riga
for j in range(colonne):
riga[j] = int(riga[j]) converto le stringhe in
numeri
mat.append(riga) inserisco la riga nella
matrice
return mat

def leggiMatriceFile1(file):
f = open(file, 'r', encoding = 'UTF-8')
dim = f.readline().split() leggo le dimensioni
['2','3']
righe = int(dim[0])
colonne = int(dim[1])
mat = [[0 for i in range(colonne)] for j in
range(righe)]

inizializzo la matrice
for i in range(righe):
riga = f.readline().split() leggo una riga
for j in range(colonne):
mat[i][j] = int(riga[j]) converto le stringhe in
numeri e li assegno alla
return mat matrice

print(open('matrice.txt',encoding='UTF-8').read())
print(leggiMatriceFile('matrice.txt'))
print(leggiMatriceFile1('matrice.txt'))

4 6
12 3 0 4 1 7
3 -2 3 7 11 0
6 8 9 11 2 -11
0 11 34 -1 9 -3

[[12, 3, 0, 4, 1, 7], [3, -2, 3, 7, 11, 0], [6, 8, 9, 11,


2, -11], [0, 11, 34, -1, 9, -3]]
[[12, 3, 0, 4, 1, 7], [3, -2, 3, 7, 11, 0], [6, 8, 9, 11,
2, -11], [0, 11, 34, -1, 9, -3]]
 Funzione che prende in input una matrice e restituisce il valore
massimo presente
 Assume che la matrice non sia vuota
def maxMatrice(mat):
massimo = mat[0][0]
for riga in mat:
for elem in riga:
if elem > massimo:
massimo = elem
return massimo

def maxMatrice1(mat):
massimo = mat[0][0]
maxi=0
maxj=0
for i in range(len(mat)):
for j in range(len(mat[0])):
if mat[i][j] > massimo:
massimo = mat[i][j]
maxi=i
maxj=j
return massimo,maxi,maxj

 per provarla importiamo la funzione precedente


from letturaMatriceFile import leggiMatriceFile

m = leggiMatriceFile('matrice.txt')
print(maxMatrice(m))
print(maxMatrice1(m))

34
(34, 3, 2)
 Funzione che prende in input una matrice e restituisce l'indice
della riga di somma massima presente
 Assume che la matrice non sia vuota

def rigaMaxMatrice(mat):
massimo = sum(mat[0]) inizializzo il massimo alla somma
della prima riga
rigamax = 0
for i in range(len(mat)):
somma = sum(mat[i])
if somma > massimo:
massimo = somma
rigamax = i
return rigamax

 per provarla importiamo la funzione precedente


from letturaMatriceFile import leggiMatriceFile

m = leggiMatriceFile('matrice.txt')
print(rigaMaxMatrice(m))

3
 Funzione che prende in input due matrici (mxn) della stessa
dimensione e restituisce una nuova matrice che è la somma
delle due

def sommaMatrici(mat1,mat2):
ris = [] inizializzo la matrice risultato
for i in range(len(mat1)):
riga = [] inizializzo la riga della matrice risultato
for j in range(len(mat1[i])):
riga.append(mat1[i][j] + mat2[i][j]) calcolo
la riga
ris.append(riga) completata la riga la inserisco nel
risultato
return ris

def sommaMatrici1(mat1,mat2):
m=len(mat1) righe
n=len(mat1[0]) colonne
ris = [[0 for j in range(n)] for i in range(m)]
inizializzo la

matrice risultato
for i in range(len(ris)):
for j in range(len(ris[0])):
ris[i][j]=mat1[i][j] + mat2[i][j] calcolo
elemento [i][j]
return ris

 per provarla importiamo la funzione precedente


from letturaMatriceFile import leggiMatriceFile

m1 = leggiMatriceFile('matrice.txt')
m2 = leggiMatriceFile('matrice2.txt')
print(sommaMatrici(m1,m2))
print(sommaMatrici1(m1,m2))
[[13, 6, 0, 0, 0, 15], [5, -4, 6, 14, 22, 0], [12, 16,
14, 17, 4, -13], [0, 13, 38, -2, 18, -6]]
[[13, 6, 0, 0, 0, 15], [5, -4, 6, 14, 22, 0], [12, 16,
14, 17, 4, -13], [0, 13, 38, -2, 18, -6]]

 Funzione che prende in input due matrici di dimensioni


compatibili (m1xn1) e (m2xn2) n1==m2 e restituisce una
nuova matrice (m1xn2) che è il prodotto delle due

def moltiplicaMatrici(mat1,mat2):
m1 = len(mat1) calcolo il numero di righe delle prima matrice
n1 = len(mat1[0]) calcolo il numero di colonne delle prima
matrice
if len(mat2) != n1: in questo caso non si possono
moltiplicare
return 'Errore, dimensioni non corrette'
n2 = len(mat2[0]) calcolo il numero di colonne della
seconda matrice
#print(n,m,p)

ris = [] inizializzo la matrice risultato


for i in range(m1):
riga = [] inizializzo la riga della
matrice risultato
for k in range(n2):
somma = 0
for j in range(n1):
somma = somma + mat1[i][j]*mat2[j][k]
riga.append(somma) aggiungo somma nella riga
risultato
ris.append(riga) completata la riga la inserisco
nel risultato
return ris

 per provarla importiamo la funzione precedente


from letturaMatriceFile import leggiMatriceFile
def moltiplicaMatrici1(mat1,mat2): dimensioni compatibili
(m1xk e kxn2 n1==m2 )
m1 = len(mat1) calcolo il numero di righe delle prima
matrice
k = len(mat1[0]) calcolo il numero di colonne delle
prima matrice
if len(mat2) != k: in questo caso non si possono
moltiplicare
return 'Errore, dimensioni non corrette'
n2 = len(mat2[0]) calcolo il numero di colonne della
seconda matrice

ris = [[0 for j in range(n2)] for i in range(m1)]

inizializzo la matrice risultato


for i in range(m1):
for j in range(n2): ciclo sul risultato r[i][j]
somma = 0 r[i][j]=(riga i mat1) X
(colonna j mat2) (lunghe k)
for rc in range(k): #o m2
somma = somma + mat1[i][rc]*mat2[rc ][j]
ris[i][j]=somma
return ris

def stampaM(mat):
for i in range(len(mat)):
for j in range(len(mat[0])):
print(mat[i][j],'\t',end = ' ') stampa la riga
separando con spazio
print() vado a riga nuova prima di stampare la
nuova riga

 per provarla importiamo la funzione precedente


from letturaMatriceFile import leggiMatriceFile

m1 = leggiMatriceFile('matrice3.txt')
m2 = leggiMatriceFile('matrice5.txt')
stampaM(m1)
print()
stampaM(m2)
print()
stampaM(moltiplicaMatrici(m1,m2))
print()
stampaM(moltiplicaMatrici1(m1,m2))

1 3 0
3 -2 3

1 3 1 1
3 -2 1 1
1 2 1 1

10 -3 4 4
0 19 4 4

10 -3 4 4
1 19 4 4

 legge una matrice di interi da un file e conta tutte le volte in


cui un elemento è la somma dei due adiacenti
3 righe 4 colonne
3 8 5 7
6 1 1 0
5 5 4 5

def leggiMatrice(file):
f = open(file,'r',encoding='utf-8')
dimensioni = f.readline().split() legge la prima riga
righe = int(dimensioni[0])
colonne = int(dimensioni[1])
mat = [[0 for j in range (colonne)] for i in
range(righe)]
for i in range(righe):
r=f.readline().split()
for j in range(colonne):
mat[i][j] = int(r[j])
f.close()
return mat
def sommaLaterali(m):
count=0
righe=len(m)
colonne=len(m[0])
for i in range(righe):
for j in range(1,colonne-1):
print(i,j)
if m[i][j]==m[i][j-1]+m[i][j+1]:
count+=1
return count
m=leggiMatrice('matrice1.txt')
print(sommaLaterali(m))

0 1
0 2
1 1
1 2
2 1
2 2
2
 legge una matrice di interi da un file e cerca il massimo
 restituisce il massimo e i suoi indici in una tupla
3 righe 4 colonne
3 8 5 7
6 1 1 0
5 5 4 5

def leggiMatrice(file):
f = open(file,'r',encoding='utf-8')
dimensioni = f.readline().split() legge la prima riga
righe = int(dimensioni[0])
colonne = int(dimensioni[1])
mat = [[0 for j in range (colonne)] for i in
range(righe)]
for i in range(righe):
r=f.readline().split()
for j in range(colonne):
mat[i][j] = int(r[j])
f.close()
return mat

def cercaMassimo(m):
mi=mj=0
massimo=m[0][0]
righe=len(m)
colonne=len(m[0])
for i in range(righe):
for j in range(1,colonne):
if m[i][j]>massimo:
massimo=m[i][j]
mi=i
mj=j
return massimo,mi,mj

m=leggiMatrice('matrice1.txt')
print(cercaMassimo(m))

(8, 0, 1)

COSA È UN CALCOLATORE
Cosa è un calcolatore Un sistema per la rappresentazione e
l’elaborazione di informazioni può
– raccogliere impressionati quantità di dati
– elaborare i dati secondo le istruzioni fornite producendo nuovi dati
– rendere disponibili questi dati in modo istantaneo e con
prospettive diverse a utenti diversi e in parti diverse del mondo

Computer (calcolatore, microprocessore…)


– Esegue semplici aritmetiche e logiche ad una velocità molto
maggiore degli essere umani
Programmi
– Insieme di istruzioni eseguibili da un computer
Hardware
– Dispositivi fisici di un sistema di elaborazione
Software
– Programmi eseguiti su un elaboratore

COSA È L’INFORMATICA
L'informatica ha a che fare con lo studio di risoluzione di problemi
(“problem solving”) per la cui soluzione si scrive un programma che
viene eseguito da un computer, l'informatica si basa su una serie di
tradizioni intellettuali che comprende aspetti della matematica e
l'ingegneria

PROGRAMMA:
Un programma è una sequenza di istruzioni scritte in un linguaggio
di rpogrammazione (e comprensibili da un calcolatore) che
realizzano l’algoritmo

DATI DI INGRESSO:
di solito un problema non deve essere una sola volta ma molte
volte con dati (di ingresso) diversi.

ELABORAZIONE DELL’INFORMAZIONE
RISOLUZIONE DI UN PROBLEMA:
1.Dato un problema si trova un algoritmo di soluzione
2.Si scrive l’algoritmo di soluzione in un programma comprensibile
da un calcolatore
3.Dato un programma, un calcolatore e dei dati di ingresso,
l’esecuzione del programma con i dati di ingresso sul calcolatore
risolve il problema su quei dati.

COME VIENE RISOLTO UN PROBLEMA:

Dati di ingresso: Elaborazione:


Dati di uscita:
Descrivono il caso in esame Manipolazione dei dati di
ingresso Rappresentano la soluzione
in modo da costruire
del caso in esame
la soluzione cercata

ALGORITMI
Un algoritmo è una “ricetta”, ovvero un procedimento, composto da
una sequenza di istruzioni elementari, che consente di risolvere un
problema.
un algoritmo deve verificare:
•I passi (le istruzioni) dell’algoritmo devono essere definiti in modo
chiaro e non ambiguo
•Efficace, nel senso che i suoi passi siano eseguibili da una
macchina
•Finito, nel senso che termina dopo un numero fissato di operazioni

PROGRAMMARE :
capacità di specializzare il dispositivo per attività complesse di
elaborazione dell’informazione;
Un programma è un algoritmo scritto in un linguaggio non ambiguo
e direttamente comprensibile dal computer.

COMPONENTI DEL COMPUTER


SOFTWARE:
•Applicazioni: È il livello di SOFTWARE con cui interagisce l’utente
•Sistema operativo: È il livello di SW che interagisce direttamente
con l’HW e che si occupa di un uso corretto ed efficiente delle
risorse fisiche
HARDWARE

LINGUAGGI DI PROGRAMMAZIONE
Per eseguire un programma scritto in un linguaggio ad alto livello
dobbiamo tradurlo nel linguaggio macchina Due possibilità
principali
• Compilatore: programma che traduce un linguaggio ad alto livello
in un linguaggio macchina
• Interprete: il programma scritto in linguaggio ad alto livello viene
simulato senza tradurlo completamente.
IL PROCESSO DI COMPILAZIONE

Programma → Compilatore → Programma Tradotto → Linker →


Programma eseguibile

Altri
programmi utili

ARCHITETTURA CPU: MODELLO DI VON NEUMANN

BUS

⬍ ⬍ ⬍

MEMORIA UNITÀ DI DISPOSITIVI


CONTROLLO INPUT/OUTPUT

REGISTRI

UNITÀ LOGICO
ARITMETICA

CPU

•Modello: una rappresentazione concettuale (spesso una


semplificazione) del mondo reale o di una sua parte, o di un
manufatto capace di spiegarne il funzionamento.
IL MODELLO DI VON NEUMANN
Il Modello di Von Neumann comprende
1.L’Unità di controllo si occupa di controllare tutte le operazioni del
calcolatore, interpretare le istruzioni prelevate dalla memoria e
inviare alle altre unità i segnali per l'esecuzione delle operazioni
2.L’Unità aritmetico-logica, detta ALU (Arithmetic & Logic Unit),
permette di effettuare operazioni aritmetiche di base e diprendere
decisioni Queste due unità sono spesso integrate in una CPU,
Central Processing Unit – Unità di Elaborazione Centrale Il modello
di von Neumann: cont.
3. La Memoria conserva le istruzioni e i dati da elaborare e i risultati
ottenuti dalle elaborazioni;
4. L’Unità di ingresso (Input) immette le informazioni nel calcolatore
per farle elaborare;
5. L’Unità di uscita (Output) riceve le informazioni dalla memoria del
calcolatore per renderle pronte all’uso; le unità di ingresso e uscita
sono anche dette periferiche
6. Il Bus, vero e proprio canale di comunicazione che consente ai
dati di transitare fra diversi componenti del calcolatore.

SOTTOSISTEMA MEMORIA

BUS

MAR MDR
Controllo
Lettura/Scrittura

Celle di Memoria

ARCHITETTURA CPU
La CPU contiene diversi registri
•Registro Istruzione (IR): memorizza l’istruzione da eseguire
•Contatore di Programma (PC): memorizza l’indirizzo in memoria
della prossima istruzione da eseguire •Registri Dati (in numero
variabile): contengono dati utilizzati per i calcoli I registri della CPU
sono aggiornati dall’esecuzione dell’istruzione

ESECUZIONE DI UN’ISTRUZIONE
1. Caricamento di un’istruzione (Fetch): con l’informazione presente
nel PC si reperisce la prossima istruzione da eseguire che viene
memorizzata in IR
2. L’unità di controllo decodifica l’istruzione: si determina il tipo di
operazione e i dati coinvolti
3. Esecuzione dell’istruzione: a seconda dell’operazione richiesta si
usa la memoria, i registri l’unità di calcolo, l’ingresso/uscita… Inoltre
si aggiorna il PC per eseguire la prossima istruzione
4. Se l’istruzione è HALT il programma termina altrimenti si inizia
l’esecuzione di una nuova istruzione

CARICAMENTO DI UN’ISTRUZIONE (FETCH)


Passi eseguiti sotto il comando dell'Unità di Controllo:
1. Copiare il contenuto del PC nel MAR (in MAR va l'indirizzo della
prossima istruzione da eseguire)
2. Impostare la linea di controllo per comunicare alla memoria la
richiesta di lettura
3. Aspettare il reperimento dell'istruzione da parte della memoria
4. Copiare il contenuto di MDR nel registro istruz. IR
•il passo 3 è necessario: non esiste un sistema di memoria che
fornisce i dati richiesti in tempo zero

• HALT (arresto del programma)


• LOAD X IND (Leggi la cella indir. IND e trasferisci il dato reg. X)
• LOADC X VALORE (Inizializza il reg X con VALORE, specificato)
• STORE X IND (Scrivi il valore reg X nella cella di indirizzo IND)
• ADD X,Y,Z (Esegui X=Y+Z, dove X, Y e Z sono registri)
• SUB X,Y,Z (Esegui X=Y-Z, dove X, Y e Z sono registri)
• MULT X,Y,Z (Esegui X=Y*Z, dove X, Y e Z sono registri)
• DIVIDE X,Y,Z (Esegui $X=Y/Z$, dove X, Y e Z sono registri)
• SQRT X,Y Esegui $X=\sqrt{Y}$, dove X e Y sono registri)
• READ IND (Leggi un valore in ingresso e ponilo cella indir. IND)
• WRITE (Scrivi in uscita il valore della cella di memoria IND)
• JUMP SALTO (Salta all’istruzione memorizzata in SALTO)
• JUMPIFZERO X, SALTO (Salta a SALTO se reg. X è zero)
• JUMPIFNEG X,SALTO (Salta a SALTO se il registro è negativo)

PRIMA LEGGE DI MOORE:


« La complessità di un microcircuito, misurata ad esempio tramite il
numero di transistori per chip, raddoppia ogni 18 mesi (e
quadruplica quindi ogni 3 anni). »
SECONDA LEGGE DI MOORE:
« Il costo di una fabbrica di chip raddoppia da una generazione
all’altra. »

CONVERSIONI
Per convertire un valore da una base a un'altra, si usa sempre la
definizione del valore di un numero:

ckck-1…c1c0 indica ck × bk + ck-1 × bk-1 + … c1 × b1 + c0 × b0


Per convertire un numero da una base qualsiasi a decimale basta
applicare la regola sostituendo a b la base a c k , ck-1 , … le cifre. Si
può anche convertire un numero da decimale a decimale: per
esempio, il numero decimale 3284 vale:

3284 = 3 2 8 4 = 3*1000 + 2*100 + 8*10 + 4*1


1000 100 10 1

La regola può venire anche applicata per convertire a decimale


numeri in binario, ottale o qualsiasi altra base. Nel caso dei numeri
in binario, il sistema è lo stesso ma invece di 1, 10, 100, 1000, ecc.,
si usano le potenze di due: 1, 2, 4, 8, 16, ecc. L'esempio che segue
mostra la conversione del numero binario 10110 in decimale:
10110 = 1 0 1 1 0 = 1*16 + 0*8 + 1*4 + 1*2 + 0*1 =
16+4+2 = 22
16 8 4 2 1

Nello stesso modo si possono convertire valori da ottale a decimale,


usando le potenze di otto, ossia 1, 8, 64, 512, 4096, ecc.
42703 = 4 2 7 0 3 = 4*4096 + 2*512 + 7*64 + 0*8 + 3*1 =
17859
4096 512 64 8 1

Altri esempi:
convertire 101101 da binario a decimale
1×2 5 + 0×2 4 + 1×2 3 + 1×2 2 + 0×2 1 + 1×2 0 = 32 + 0 +
8 + 4 + 0 + 1 = 45

convertire 5720 da ottale a decimale


5×8 3 + 7×8 2 + 2×8 1 + 0×8 0 = 2560 + 448 + 16 + 0 =
3024
convertire 43012 da base cinque a decimale
4×5 4 + 3×5 3 + 0×5 2 + 1×5 1 + 2×5 0 = 2500 + 375 + 0 +
5 + 2 = 2882
convertire 6513 da base sette a decimale
6×7 3 + 5×7 2 + 1×7 1 + 3×7 0 = 2058 + 245 + 7 + 3 = 2313

CONVERTIRE DA DECIMALE IN ALTRA BASE

Il sistema visto sopra permette di convertire da una qualsiasi base a


decimale. La conversione opposta, da decimale ad altra base, si
effettua con una serie di divisioni successive. Per esempio, per
convertire un numero da decimale a binario:
 si calcolano quoziente e resto di n diviso due
 il resto è l'ultima cifra binaria
 il quoziente si divide per due, ottenendo un nuovo quoziente e
resto
 il resto è la penultima cifra binaria i
 l quoziente si divide per due...
Il metodo termina quando il quoziente vale zero.
 Per esempio,319 si converte in binario così:
 319 diviso due fa 159 con resto di uno
 159 diviso due fa 79 con resto di uno
 79 diviso due fa 39 con resto di uno
 39 diviso due fa 19 con resto di uno
 19 diviso due fa 9 con resto di uno
 9 diviso due fa 4 con resto di uno
 4 diviso due fa 2 con resto di zero
 2 diviso due fa 1 con resto di zero
 1 diviso due fa 0 con resto di uno
La rappresentazione binaria di 319 si ottiene prendendo i resti in
ordine inverso, dall'ultimo al primo: 100111111.

Lo stesso metodo si applica per la conversione in qualsiasi altra


base, per esempio otto. Lo stesso valore 319 si converte in ottale
così:
 319 diviso otto fa 39 con resto di 7
 39 diviso otto fa 4 con resto di 7
 4 diviso otto fa 0 con resto di 4
Il numero in ottale si ottiene prendendo i resti in ordine inverso, ed
è quindi 477.

CONVERSIONE CON BASI ENTRAMBE DIVERSE DA DIECI


Volendo effettuare una conversione da base cinque a base otto, si
può procedere in due passi successivi: prima si converte in
decimale, poi da decimale a ottale. Per esempio, il numero 3421 in
base cinque si converte in ottale così:
1. si converte in decimale: 3421 = 3 × 5×5×5 + 4 × 5×5 + 2 × 5
+ 1 = 486
2. il numero decimale 486 si converte in base otto con divisioni
successive: 486/8 = 60 con resto di 6, poi 60/8=7 con resto di 4, poi
7/8 vale zero con resto di 7; il numero in ottale è quindi 746
La conversione si può fare in un modo più semplice se la base di
partenza o di arrivo hanno gli stessi numeri
nella scomposizione in primi. Per esempio, per convertire da base
due a otto o viceversa, si può sfruttare il
fatto che 8 = 2×2×2. Per esempio, su un numero binario di sei
cifre:

c5× 2×2×2×2×2 +c4 × 2×2×2×2 +c3 × 2×2×2 +c2 × 2×2 +c1 ×2 +


c0 =
d1 × 8 + d0

In questa espressione, d1d0 è il numero in ottale. Raggruppando le


cifre binarie per tre, si ottiene:

(c5 × 2×2 + c4 × 2 + c3 ) × 8 + ( c2 × 2×2 + c1 × 2 + c0 )


=
d1 ×8 + d0

Il valore massimo di c5 × 2×2 + c4 × 2 + c3 è sette: 1×4 + 1×2


+ 1=4+2+1=7. Questa espressione fornisce quindi il valore di d1 ,per
lo stesso motivo, c2 × 2×2 + c1 × 2 + c0 è d0.

In generale, per convertire da binario a ottale si raggruppano le


cifre binarie in gruppi da tre e si converte
ogni terzina in ottale. Per esempio, il numero binario 11010111001
si converte in base otto scomponendolo in
terzine (in questo caso occorre aggiungere uno zero davanti):

11010111001 = 011 010 111 001 = 3271


--- --- --- ---
3 2 7 1

Lo stesso sistema si può usare nel senso inverso: per convertire da


ottale a binario, si prende ogni singola
cifra ottale e la si converte in binario.
52172 = 5 2 1 7 2 = 101 010 001 111 010 = 101010001111010
--- --- --- --- ---
101 010 001 111 010
Lo stesso sistema si può usare per convertire da binario a base
sedici, dato che 16=2×2×2×2, e viceversa. In
questo caso, ogni cifra esadecimale corrisponde a quattro cifre
binarie. Da decimale a esadecimale:
10101111001 = 0101 0111 1001 = 579
---- ---- ----
579
Da esadecimale a binario:
791 = 7 9 1 = 0111 1001 0001 = 011110010001
---- ---- ----
0111 1001 0001
ESADECIMALE
Una base molto usata in informatica è il sedici, proprio perchè una
cifra esadecimale corrisponde a quattro binarie. In base sedici,
occorrono sedici cifre. Per le prime dieci si usano quelle normali 0,
…, 9, per le sei che mancano le lettere A, B, C, D, E ed F. La
successione dei primi numeri espressi in esadecimale è la seguente:
 0 zero
 1 uno
 2 due
 3 tre
 4 quattro
 5 cinque
 6 sei
 7 sette
 8 otto
 9 nove
 A dieci
 B undici
 C dodici
 D tredici
 E quattordici
 F quindici
 10 sedici
 11 diciassette
 12 diciotto
 13 diciannove
 14 venti
 15 ventuno
 ...
Per le conversioni si usa sempre lo stesso sistema. Un numero
esadecimale si converte in decimale calcolando il valore del
polinomio e tenendo conto che A vale dieci, B vale undici, ecc.
A2F = A×16×16 + 2×16 + F =
= 10×16×16 + 2×16 + 15 =
= 2607
Un numero decimale si converte in esadecimale con il sistema delle
divisioni successive. Per esempio, il numero decimale 2607 si
converte facendo prima 2607/16, che è 162 con il resto di 15, che
fornisce l'ultima cifra F, dato che F vale quindici. Dividendo 162 si
ottiene la penultima cifra e via dicendo.
La conversione da binario a esadecimale è più facile visto che 16 =
2×2×2×2. Basta infatti prendere le cifre binarie in gruppi da
quattro e convertire ogni singolo gruppo, che fornirà una cifra
esadecimale. Nella direzione opposta, una cifra esadecimale
corrisponde a un gruppo di quattro cifre binarie.

ADDIZIONI
La normale somma in decimale si fa con il solito sistema di mettere
i due addendi in colonna e sommare cifra con cifra più l'eventuale
riporto. Per esempio, 275+1754:
275+
1754=
---------

5+4=9

7+5=12, ossia 2 con riporto 1

2+7+1=10, ossia 0 con riporto 1
↓ 1+1=2
----------
2029

Si usa lo stesso sistema in tutte le rappresentazioni posizionali, a


prescindere dalla base: si somma cifra per cifra, e se il valore è
maggiore di una singola cifra (nell'esempio, 7+5=12 è di due cifre)
la prima (in questo caso 1) si mette nella somma successiva.
In ottale, 523+1361:
523+
1361=
---------

3+1=4

2+6=otto, in ottale 10, ossia 0 con riporto di 1
↓ 5+3+1=nove, in ottale 11, ossia 1 con riporto di 1

1+1=2
---------
2104
Il risultato è 2104. Nel sommare le penultime cifre, si ottiene
2+6=10. Infatti, 10 è otto in ottale. Di questo 10, la penultima cifra
del risultato è 0, mentre 1 viene riportato nel fare la somma
successiva.

In binario, 11011+100101:
10011+
100111=
-------------
↓ 1+1=due, in binario 10, ossia 0 con riporto 1
↓ 1+1+1=tre, in binario 11, ossia 1 con riporto 1
↓ 0+1+1=due, in binario 10, ossia 0 con riporto 1
↓ 0+0+1=1 ↓ 1+0=1
↓1
-------------
111010
È come in decimale, ma la somma fra le singole cifre va fatta nella
base considerata: in ottale 5+3+1=11, in binario 1+1+1=11.

SOTTRAZIONE
La sottrazione si effettua nel solito modo: si sottraggono le singole
cifre, con eventuale riporto di -1. Il sistema sfrutta ancora due
proprietà del sistema posizionale:
 le due cifre nella stessa posizione sono moltiplicate per la
stessa potenza della base, per cui si può fare cifra-cifra;
 le cifre vanno da 0 a b-1, per cui cifra-cifra-1 vale al minimo 0-
(b-1)-1=-b+0, che produce appunto il riporto massimo di meno
uno.

Una sottrazione in decimale:


321–
62=
---------
↓ 1-2=-1, ossia 9-10: cifra 9 e riporto -1
↓ 2-6-1=-5, ossia 5-10: cifra 5 e riporto -1
↓ 3-1=2
---------
259
I risultati negativi come -1 si esprimono come 9-10, ossia si mettono
in una forma cifra-10. La cifra si scrive in basso nel risultato, il -10
diventa un riporto -1.

È simile al metodo delle addizioni, dove ottenere 19=10+9 significa


che la cifra del risultato è 9 e il riporto 1. In termini matematici, 10
per questa cifra equivale a 1 per la cifra precedente.
Per le sottrazioni, -10 per questa cifra equivale a -1 per la cifra
precedente. Questo perchè la penultima cifra è moltiplicata per 10,
mentre la terzultima per 100. Quindi un dieci per la penultima
uguale a dieci per la terzultima, e lo stesso per meno dieci e meno
uno.

Questo che si è detto per il dieci vale per qualsiasi base.


Per esempio, la seguente è una sottrazione in ottale:
271–
136=
---------
↓ 1-6=-5=3-8, ossia cifra 3 e riporto -1
↓ 7-3-1=3
↓ 2-1=1
---------
133
Dato che la base è 8, il numero negativo -5 è stato riscritto come 3-
8, che equivale a (-1)×8+3. È nella stessa forma di 13=1×8+3 in
ottale, ma è come se che la prima cifra fosse negativa: (-1)3. Per
questo il riporto è -1.

Detto in un altro modo: nel polinomio che dice il valore di un


numero, l'ultima cifra è moltiplicata per uno; la penultima per otto.
Questo vuol dire che un -8 all'ultima cifra è uguale a -1 alla
penultima (che è moltiplicata per otto).

Per questo motivo, -5=3-8 produce un 3 come ultima cifra del


risultato e -1 come riporto.

Lo stesso metodo si usa anche in binario, come si vede da questa


sottrazione in binario: 1
100100–
1001011=
----------------
↓ 0-1=-1=1-2, ossia 1 con riporto di -1
↓ 0-1-1=-2=0-2, ossia 0 con riporto di -1
↓ 1-0-1=0 ↓ 0-1=-1=1-2, ossia 1 con riporto di -1
↓ 0-0-1=-1=1-2, ossia 1 con riporto di -1
↓ 1-0-1=0
↓ 1-1=0
----------------
0011001

Come si vede, in binario si può ottenere una "cifra negativa" come


0-1=-1, che corrisponde a (-1)×2 + 1, ossia cifra 1 e riporto -1. A
sua volta, il riporto può far sì che la somma successiva sia 0-1-1=-
2=(-2)*2+0, ossia cifra 0 e riporto -1.
MOLTIPLICAZIONE
La moltiplicazione in base qualsiasi si calcola come in decimale: il
moltiplicando per ogni cifra del moltiplicatore. Per esempio, in
ottale:
412 ×
52 =
------
1024 ← 412 × 2, tenendo conto che 4×2=10
2462 ← 412 × 5, tenendo conto che 5×2=12 e 5×4=24
------
25644 ← somma

In binario, il meccanismo si semplifica perchè ogni cifra può valere


solo zero oppure uno. Il prodotto del moltiplicando per una cifra del
moltiplicatore può quindi essere o zero oppure il moltiplicando
stesso:
10111 ×
1101 =
---------
10111 ← 10111×1
00000 ← 10111×0
10111 ← 10111×1
10111 ← 10111×1
---------
100101011
La moltiplicazione per zero dà sempre come risultato zero, mentre
la moltiplicazione per uno dà come risultato il primo numero
spostato di un certo numero di posizioni.

CONVERSIONE IN FORMATO BINARY16

La sequenza di bit 1 01101 0011001000 è un numero in binary16,


ossia un numero frazionario in virgola mobile espresso con un bit di
segno, cinque di esponente in eccesso 15 e il resto mantissa.
Convertirlo in decimale.
Il primo bit 1 = bit per il segno: 0 = +; 1 = – quindi il nostro
numero ha il segno –
Esponente = N – BIAS
BIAS = 2k-1 – 1 (dove k è il numero di bit con i quali viene codificato
l’esponente; nel nostro caso 5) quindi avremo:
BIAS = 25-1 – 1 = 24 – 1 = 16 – 1 = 15
N = (01101)2 = 8+4+1 = 13 in base 10
Esponente = N – BIAS = 13 – 15 = –2
Consideriamo ora la Mantissa e trasformiamola in numero decimale

0 - - - - - - - - - - esponente
1 2 3 4 5 6 7 8 9 1
0
1 . 0 0 1 1 0 0 1 0 0 0 mantissa

20+2-3+2-4+2-7 = = 1+0,125+0,0625+0,078125 =

1,1953125 = 1,195 (abbiamo considerato solo 3 cifre significative


dopo la virgola)

Dalla formula F = +/– M•2E cioè il numero F (floating) = segno (+ o


–) Mantissa per 2 elevato all’Esponente avremo:
F = –1,195•2-2  –0,2988

Convertire il numero decimale 0,21 in formato binary16: un


bit di segno, cinque di esponente in eccesso 15 e il resto
mantissa.
Convertiamo la parte intera del numero (0)10 = (0)2
Ora convertiamo la parte decimale con il complemento a 2

0,21x2=0,42 cifra più significativa


0,42x2=0,84
0,84x2=1,68
0,68x2=1,36
0,36x2=0,72
0,72x2=1,44
0,44x2=0,88
0,88x2=1,76
0,76x2=1,52
0,52x2=1,04
0,04x1=0,08
0,08x2=0,16
0,16x2=0,32 cifra meno significativa
Scriviamo il numero sommando la parte intera a quella decimale
(partendo a scrivere il numero binario della parte decimale dalla
cifra più significativa):

0 + 0.0011010111000

Partendo da 0. per avere la prima cifra significativa 1 dobbiamo


compiere 3 salti ottenendo:
1.1010111000•2-3 il nostro esponente è quindi -3
BIAS = 2k-1 – 1 (dove k è il numero di bit con i quali viene codificato
l’esponente; nel nostro caso 5) quindi avremo:
BIAS = 25-1 – 1 = 24 – 1 = 16 – 1 = 15
Dalla formula Esponente = N – BIAS ricaviamo N
N = E+BIAS = -3 +15 = 12 che convertiamo in base 2
(12)10 = (01100)2 per cui il numero binario finale
avrà segno positivo (0), Esponente = 12 (01100) e Mantissa =
1010111000
Il numero decimale 0,21 in binary16 = 0 01100 1010111000
NUMERI FRAZIONARI
In generale, un numero frazionario 0,c1c2c3…, ossia uno che ha dopo
la virgola le cifre c1 , c2 , c3 , ecc., significa:

0,c1c2c3… = c1×10-1 + c2×10-2 + c3×10-3 + …

Questo nel caso decimale. Si estende a base b usando b al posto di


dieci:

0,c1c2c3… = c1×b-1 + c2×b-2 + c3×b-3 + …

Nel caso si voglia convertire questo numero in decimale, basta


effettuare i calcoli. Per esempio, il numero ottale 0,645 vale:

0,645 = 6×8 -1 + 4×8 -2 + 5×8 -3 = 6/8 + 4/(8×8) + 5/(8×8×8) =


0,822265625

Il numero binario 0,110101 si converte nello stesso modo: 0,110101


= 1×2 -1 + 1×2 -2 + 0×2 -3 + 1×2 -4 + 0×2 -5 + 1×2 -6 = 1/2 +
1/4 + 0/8 + 1/16 + 0/32 + 1/64 = 0,828125

Nel caso di conversione fra due basi che sono l'una potenza
dell'altra, come nel caso di 2 e 16, allora si possono raggruppare le
cifre come per la conversione fra numeri interi. Per esempio, il
numero binario 0,11011000 è uguale all'esadecimale che ha cifre
1101=D e 1000=8, ossia 0,D8.

Per effettuare la conversione ad altra base si usa il metodo delle


moltiplicazioni successive, simile a quello delle divisioni successive
visto per la conversione degli interi.

Per convertire un numero da decimale a base b:


 moltiplicare il numero per b;
 togliere la parte intera, che è la prima cifra;
 moltiplicare quello che rimane per b; …
Per esempio, il numero decimale 0,6875 si converte in binario come
segue:
 0,6875×2 = 1,375
 la parte intera è uno; sottratta, lascia
 0,375 0,375×2 = 0,75
 la parte intera è zero;
 0,75×2 = 1,5
 la parte intera è uno; si toglie, lasciando
 0,5 0,5×2 = 1
 la parte intera è uno; togliendola, rimane 0

Le cifre binarie sono le parti intere in ordine (non in ordine opposto


come nella conversione di interi). In questo caso, 0,1011.

La procedura termina quando il valore che rimane è zero. Non è


però sempre detto che la procedura termini. Per esempio, la
conversione di 0,2 produce:
 0,2×2=0,4
 0,4×2=0,8
 0,8×2=1,6, parte intera 1
 0,6×2=1,2, parte intera 1
 0,2×2=0,4
 …

Si è tornati a 0,2, per cui si ripete tutto uguale, tornando ancora a


0,2. Il numero binario che si ottiene è quindi 0,001100110011…,
dove le cifre 0011 si ripetono all'infinito.

Questo avviene perchè 0,2=1/5. Dato che 10=2×5, ossia il dieci


contiene il cinque come numero primo, la rappresentazione in base
dieci è finita: 0,2=1/5=2/10. D'altra parte, due non contiene cinque
come numero primo, per cui la rappresentazione di 0,2=1/5 in base
due non è finita: non c'è modo di ottenere 1/5 come somma di
potenze di due 1/2, 1/4. 1/8, ecc.

Questa proprietà vale in generale: se la base di arrivo contiene tutti


i numeri primi di quella di partenza allora un numero frazionario con
cifre finite si converte sempre in uno con cifre finite. Nel caso
contrario, questo può o meno avvenire a seconda dei casi: 1,375 si
convertiva in un numero binario con cifre finite, 0,2 no.

NUMERI CON PARTE SIA INTERA CHE FRAZIONARIA


Per convertire un numero composto sia da una parte intera che da
una frazionaria, si convertono separatamente le due parti. In
generale, un numero ck…c0,c-1c-2… in base b vale:

ck…c0,c-1c-2…= ck×bk + … c0×b0 + c-1×b-1 + c-2×b-2+ … = ∑i=k,k-1,…


ck×bk

Esempio: convertire 12,6875 in binario.


Si converte prima la parte intera e poi quella frazionaria. Per quella
intera si usano le divisioni successive su 12:
 12 diviso 2 fa 6 con resto di 0
 6 diviso 2 fa 3 con resto di 0
 diviso 2 fa 1 con resto di 1
 1 diviso 2 fa 0 con resto di 1

La parte intera è 1100 perchè questi sono i resti in ordine inverso.


Per la parte frazionaria si effettuano le moltiplicazioni successive su
0,6875:
 0,6875 per 2 fa 1,3750, parte intera 1
 0,3750 per 2 fa 0,7500, parte intera 0
 0,7500 per 2 fa 1,5000, parte intera 1
 0,5000 per 2 fa 1,0000, parte intera 1
Le parti intere vanno prese nell'ordine, per cui la parte frazionaria in
binario è 0,1011. Nel complesso, il numero si traduce in binario in
1100,1011.

VIRGOLA MOBILE
Nella rappresentazione in virgola fissa si decide in anticipo il
numero di bit da usare prima e dopo la virgola. In quella mobile, si
usa sempre un numero prefissato totale di bit, ma la posizione della
virgola all'interno di questi può variare. Dal momento che il numero
cambia a seconda della posizione della virgola:

la posizione della virgola fa parte della rappresentazione del


numero

Il numero viene quindi rappresentato come una parte chiamata


mantissa che indica il suo valore (senza la virgola) e una parte
chiamata esponente che indica la posizione della virgola al suo
interno. Per esempio:
351#0
valore 351 con virgola in posizione zero, ossia 0,351
1023#1
valore 1023 con virgola in posizione uno, ossia 1,023

1023#2
valore 1023 con virgola in posizione due, ossia 10,23
21#5
valore 21 con virgola in posizione cinque, ossia 21000,0
7214#-3 valore 7214 con virgola in posizione meno tre, ossia
0,0007214

Come si vede da questi esempi, la posizione della virgola indica di


quanto va moltiplicato il numero, considerato come un valore
frazionario 0,cifre. In particolare, per la posizione zero il numero
rimane inalterato, per la posizione uno il numero è moltiplicato per
dieci, per la posizione due si moltiplica per cento, ecc. In altre
parole, dal punto di vista matematico la posizione indica una
potenza di dieci da moltiplicare al valore iniziale.

 351#0 è 0,351 × 1 = 0,351


 1023#1 è 0,1023 × 10 = 1,023
 1023#2 è 0,1023 × 100 = 10,23
 21#5 è 0,21 × 10 5 = 21000
 7214#-3 è 0,7214 × 10 -3 = 0,0007214

In generale, nelle rappresentazioni in virgola mobile in base b, ogni


numero viene rappresentato nel seguente modo:

n = m × be

Invece di memorizzare n, vengono memorizzati la mantissa m e


l'esponente e. Come si è visto sopra, l'esponente si può vedere
come la posizione della virgola all'interno di m, assumendo che m
sia un numero nella forma 0,cifre. Questa su m non è una
limitazione, dato che ogni numero si può esprimere in questa forma,
visto che è possibile moltiplicarlo per l'esponente per ottenere
valori più piccoli e più grandi.

Il motivo per cui la rappresentazione in virgola mobile è quella


usata di norma per i valori frazionari è che permette di memorizzare
una gamma di valori più ampi, molto grandi e molto piccoli, a
scapito di una perdita di precisione che è però piccola rispetto alla
grandezza dei valori in esame. Per esempio:
 fra 100 e 200 c'è una certa differenza;
 fra 100000000100 e 100000000200 no.

In virgola fissa tutti e quattro i numeri sono rappresentati in modo


esatto, sempre che la quantità di bit disponibile sia sufficiente.
Questo vuole dire che 100000000100 e 100000000200 potrebbero
non essere rappresentabili, ma se lo sono allora sono sequenze di
bit diverse.

In virgola mobile, gli stessi due numeri sono 100000000100#12 e


100000000200#12. Se i bit non bastano, si possono omettere le
ultime cifre, limitandosi per esempio alle prime sei. Si otterrebbero
così 100000#12 = 0,1×10 12 e 100000#12 = 0,1×10 12 . Questi
due numeri sono uguali, ma del resto erano già molto simili in
origine: 100000000100 e 100000000200; la differenza si può
considerare in molti casi trascurabile. D'altra parte, i numeri 100 e
200 verrebbero rappresentati come diversi: 1#3 e 2#3.

Usando le sei cifre della mantissa più le due dell'esponente per


rappresentare i numeri in virgola fissa, il totale di otto cifre non
basterebbe per rappresentare i due numeri 100000000100 e
100000000200, che hanno dodici cifre. In altre parole, questi due
numeri che sono rappresentati in forma approssimata con la virgola
mobile non si possono rappresentare affatto con la virgola fissa.

Riassumendo, in virgola mobile è possibile rappresentare la "parte


principale" di un numero (le sue prime cifre), trascurando
eventualmente quello che resta se lo spazio a disposizione non
consente di memorizzare tutto.

CALCOLI IN VIRGOLA MOBILE


La rappresentazione in forma di mantissa ed esponente causa delle
difficoltà aggiuntive quando occorre fare calcoli. Per esempio, i
numeri 101#3 e 2#2 non si possono sommare facendo la somma
delle mantisse:
101+2
errato, perchè 101#3 significa 101 ma 2#2 significa 20;
0,101+0,2
errato, perchè 101#3=0,101×10 3 mentre 2#2=0,2×10 2 , e
quindi 0,101 e 0,2 sono moltiplicati per due diverse potenze di
dieci.
La somma dovrebbe essere 121 = 121#3, invece nel primo caso
viene 103 e nel secondo 301#3 o 301#2 a seconda di quale
esponente si usi.

 Dal momento che i numeri espressi possono essere molto


grandi o molto piccoli, si preferisce evitare di ridurli alla forma
esplicita (come si è fatto in questo esempio con 101 e 20), ma
si utilizza un diverso sistema: si modifica il numero con
esponente più piccolo in modo che abbia lo stesso esponente
dell'altro;
 si sommano le mantisse;
 se il risultato è maggiore o uguale a uno, si divide per dieci e si
aumenta l'esponente di uno.

Nell'esempio, 2#1 ha l'esponente minore, quindi è quello che va


modificato. Dal momento che 2#1 = 0,2×100 = 20, questo numero
si può anche rappresentare come 0,02×1000. Ora che entrambi i
numeri sono moltiplicati per mille, si può effettuare la somma delle
mantisse:
0,101×1000 + 0,02×1000 = (0,101+0,02) × 1000

La somma 0,101+0,02 = 0,121 produce il risultato corretto:


0,121×1000 = 121#3.

 In questo caso non è stato necessario il terzo passo della


procedura, dal momento che il risultato 0,121 della somma
delle mantisse era minore di uno. Questo può però succedere,
come quando si sommano 95#2 e 7#1: si uguagliano gli
esponenti: 7#1 = 0,7×10 = 0,07×100 = 07#2;
 si sommano le mantisse: 95+07 = 102;
 il risultato non è 102#2 = 0,102×100 ma 1,02×100, ossia
102#3.

In altre parole, se il risultato della somma ha una cifra in più,


occorre aumentare l'esponente di uno. Modificare l'esponente in
modo che la mantissa abbia la forma 0,cifre si chiama
normalizzazione.
In decimale, un numero nella forma 0,cifre, in cui la prima cifra è
diversa da zero, risulta compreso fra 0,1 e 0,9999…, ossia fra 0,1
(incluso) e 1 (escluso).

ALGORITMO DI SOMMA
Le operazioni necessarie per la somma sono facili da realizzare in
pratica. Il cambio di esponente è una divisione della mantissa per
una potenza di dieci e un aumento dell'esponente di questo valore.
Per esempio:

0,9561 × 103 = 0,09561 × 104

Il numero 9561#3 diventa quindi 09561#4: è stato aggiunto uno


zero all'inizio della mantissa e l'esponente è stato aumentato di
uno. Allo stesso modo, per portare 42#5 a esponente 8, bisogna
aggiungere tre zeri alla mantissa: 42#5=00042#9.

In generale, per aumentare l'esponente di x, bisogna aggiungere x


zeri davanti alla mantissa.

Per la somma, due numeri 0,cifre e 0,altrecifre si possono sommare


come se fossero interi, aggiungendo abbastanza zeri in fondo in
modo che il numero totale di cifre sia lo stesso:

0,1342 + 0,01 = 0,1342 + 0,0100 → 1342 + 0100

La eventuale normalizzazione che fa fatta dopo la somma consiste


in una semplice diminuzione dell'esponente di uno. Infatti, se la
somma 1cifre rappresenta 1,cifre, basta diminuire l'esponente di
uno per ottenere 0,1cifre. Le cifre della mantissa sono quindi
sempre 1cifre ossia quello che si otteneva nella somma fra interi.

Dovendo sommare a#b e c#d, i passi da fare sono:


1. se b < d si converte a#b in 0…0a#d, dove gli zeri aggiunti sono
d-b;
2.se b>d, si fa lo stesso su c#d;
3. si aggiungono zeri in fondo a 0…0a e c in modo che abbiano la
stessa lunghezza;
4. si sommano come interi: e = 0…0a0…0 + c0…0;
5. se la somma produce una cifra in più allora f=d-1, altrimenti f=d;
6. il risultato è e#f

Per esempio, per sommare 994#3 con 6169#1 con quattro cifre
mantissa e due di esponente, si procede nel modo seguente:
aumentare l'esponente minore:
in questo caso l'esponente minore è quello del secondo numero, per
cui 7169#1 si trasforma in 007169#3; uguagliare il numero di cifre
delle mantisse:
dei due numeri 994#3 e 007169#3, il secondo ha più cifre; si
aggiungono zeri al primo, trasformando 994#3 in 994000#3
somma fra interi:
è una normale somma:
994000 +
007169 =
----------
1001169

Normalizzare:
è venuta una cifra in più, per cui occorre normalizzare; l'esponente
maggiore dei due numeri, cioò tre, va aumentato di uno:
l'esponente del risultato è quindi 3+1=4;
limitare le cifre:
il risultato della somma ha troppe cifre (sette invece di quattro); se
ne prendono solo quattro, per cui la mantissa del risultato è 1001;

Il risultato della somma è quindi 1001#4. La sequenza di passi non


ha richiesto altro che confronto fra interi, aggiunte di zeri a sinistra
e a destra, una somma fra interi e una eventuale sottrazione di uno.

Altro esempio: somma dei numeri 6002#-1 e 12#2 con quattro cifre
di mantissa e una di esponente:
 esponente minore: 6002#-1=0006001#2
 stesso numero di cifre: 12#2=1200000#2
 somma:
0006001 +
1200000 =
-----------
1206001
 non è aumentato il numero di cifre, non si diminuisce
l'esponente
 risultato: 1206#2

In questo caso alla mantissa del primo numero sono stati aggiunti
tre zeri a sinistra. Se gli zeri fossero stati maggiori del numero di
cifre disponibili per la mantissa, si poteva concludere subito la
somma: il risultato era uguale all'altro numero.

Invece di togliere le cifre in eccesso dal risultato, le si poteva


eliminare dagli operandi prima di sommare. Questo produce lo
stesso risultato, visto che l'addendo che in origine aveva
l'esponente maggiore poteva avere solo zeri come cifre aggiuntive.
In altre parole, le cifre eliminate non avrebbero comunque prodotto
un riporto. Nell'esempio:

0006001 + 0006 +
1200000 = 1200 =
----------- → --------
1206001 1206
In questo caso, 12#2 ha due cifre di mantissa, ma al massimo
potevano essere quattro. Quelle dopo sarebbero state zeri.
Sommate all'altro numero non avrebbero comunque prodotto un
riporto. Il risultato è quindi uguale a sommare i numeri con le cifre
in più e poi troncare il risultato.

VIRGOLA MOBILE IN BASE GENERICA


Finora si sono usati numeri in base dieci. Lo stesso sistema di
mantissa ed esponente si può realizzare anche in una base diversa
da dieci, per esempio in binario. Si può procedere in due modi:
 si continua a usare la regola 0,mantissa × 10 esponente , ma
ora sia la mantissa che l'esponente si rappresentano in binario
 si lavora nella base scelta, in questo caso il binario: sia
l'esponente che la mantissa sono numeri binari, e il valore
rappresentato è 0,mantissa × 2 esponente

In altre parole, il secondo sistema differisce perchè è 2 che viene


elevato all'esponente piuttosto che 10. Per convertire un numero da
decimale a questa forma, occorre prima esprimerlo in binario, poi
verificare quanti spostamenti di virgola occorre effettuare per
portarlo nella forma 0,cifre, con la prima cifra diversa da zero.

Questa operazione di riportare la mantissa nella forma scelta va


effettuata anche dopo aver fatto una somma, in particolare quando
il risultato della somma delle mantisse è maggiore di uno. In questo
caso, occorre infatti dividere la mantissa per due (la base) e
aumentare l'esponente di uno. In generale, la normalizzazione in
binario consiste in:
aumentare o diminuire l'esponente in modo che la
0,mantissa sia compresa fra 0,1 (incluso) e 1
(escluso)

In binario, 0,1=1/2. In generale, 0,mantissa deve venire portato con


divisioni o moltiplicazioni per la base b a un valore fra 1/b incluso e
1 escluso.
Questa operazione è sempre possibile, dal momento che qualsiasi
sia la prima cifra c diversa da zero del numero, sia esso nella forma
c… (prima cifra diversa da zero intera) oppure 0,0…0c… (prima
cifra diversa da zero frazionaria), questo si può moltiplicare o
dividere per la base fino a farlo diventare 0,c…, che è appunto
compreso fra 0,1 e 1.

Per esempio, il numero decimale 123,75 si converte nel modo


seguente in una rappresentazione binaria in virgola mobile con otto
bit di mantissa e quattro di esponente.

Per prima cosa si converte la parte intera 123 usando il metodo


delle divisioni successive. Si ottiene 1111011. Si converte poi la
parte frazionaria 0,75 con il metodo delle moltiplicazioni successive,
ottenendo 0,11. Il numero in virgola fissa sarebbe quindi
1111011,11.

L'esponente si trova contando le cifre intere. In questo caso sono


sette, per cui l'esponente è sette, cioè 0111. La mantissa è data dai
primi otto bit, senza la virgola: 11110111.

Il risultato è quindi 11110111#0111.

Come si vede da questo esempio, l'ultimo bit della parte frazionaria


non è stato usato. In generale, nella conversione della parte
frazionaria ci si può fermare quando si arriva all'ultimo bit che può
entrare in mantissa. Nel caso di otto bit, dopo sei di parte intera e
uno di parte frazionaria, è inutile proseguire con le moltiplicazioni
successive per ottenere i bit seguenti.

Questo è particolarmente importante per numeri come 0,2 che


hanno un numero infinito di bit frazionari. In questi casi, basta
fermarsi quando sono stati ottenuti tutti i bit (sia nella parte intera
che frazionaria) della mantissa.
Per esempio, nella conversione del numero 0,135 con otto bit di
mantissa e quattro di esponente, le moltiplicazioni successive
producono:
 0,135 per 2 fa 0,270, parte intera 0
 0,270 per 2 fa 0,540, parte intera 0
 0,540 per 2 fa 1,080, parte intera 1
 0,080 per 2 fa 0,160, parte intera 0
 0,160 per 2 fa 0,320, parte intera 0
 0,320 per 2 fa 0,640, parte intera 0
 0,640 per 2 fa 1,280, parte intera 1
 0,280 per 2 fa 0,560, parte intera 0
 0,560 per 2 fa 1,120, parte intera 1
 0,120 per 2 fa 0,240, parte intera 0
 0,240 per 2 fa 0,480, parte intera 0
 0,480 per 2 fa 0,960, parte intera 0
 0,960 per 2 fa 1,920, parte intera 1
 …

Si ottiene quindi 0,0010001010001…, seguito da altri bit al


momento non calcolati. Ci si poteva però anche fermare prima.
Infatti, la conversione produce:
0,0010001010001… → 10001010#-2
|------|
otto bit
In altre parole, solo gli otto bit dopo il primo uno verranno usati. La
conversione si completa rimpiazzando -2 con il suo valore binario,
ossia 1110 (in complemento a due). Il risultato è quindi
10001010#1110.
Come esercizio, si converta il numero 2,991 in binario con otto bit di
mantissa e quattro di esponente.

La conversione della parte intera 2 produce 10. Per la parte


frazionaria, le prime sei moltiplicazioni successive di 0,991
generano 0,111111. Ci si ferma alla sesta moltiplicazione perchè
con i due bit della parte intera si è già arrivati agli otto bit della
mantissa. Il numero in binario è 10,111111.

La mantissa sono gli otto bit senza la virgola, quindi 10111111.


L'esponente è il numero di cifre decimali, quindi 2=0010. Il risultato
è quindi 10111111#0010.

FORMATO IEEE 754


Un formato per numeri in virgola mobile usato in pratica è IEEE 754,
che nel caso a 64 bit rappresenta i numeri in binario con:
 un bit di segno
 11 bit di esponente
 52 bit di mantissa

LOGICA PROPOSIZIONALE
 valori: falso, vero (oppure: 0 e 1)

 connettivi: ¬ ∧ ∨ (cioè NON, E, OPPURE)


 variabili: a, b, c, …

SODDISFACIBILITÀ
formula F
verificare se ha un modello o
ppure: trovare un modello (se esiste)
modello = valori di ingresso che producono 1 in uscita

a ∧ b ∧ ¬a
Esempio:

vale 1 solo se sia a che ¬a valgono 1


impossibile
formula insoddisfacibile

¬b ∧ (a ∨ b) c
on a=1 e b=0
la formula è vera soddisfacibile

(a ∨ ¬b) ∧ ¬a ∧ (b ∨ a)
METODI AUTOMATICI

(a ∨ ¬b) ∧ ¬a ∧ (b ∨ a) =
applicando la regola (F∨c)∧(F∨¬c) = F:

(a ∨ ¬b) ∧ ¬a ∧ (b ∨ a) ∧ a = 0
infatti: a∧¬a=0
formula insoddisfacibile

SEMPLIFICAZIONE
(a E (NON b) E (NON c)) OPPURE (a E (NON b) E c)
a parole, due possibilità:
 a E (NON b) E (NON c)
 a E (NON b) E c
ossia a E (NON b), e poi o c oppure NON c

FATTOR COMUNE
(a E (NON b) E (NON c)) OPPURE (a E (NON b) E c) =
(a E (NON b)) E (c OPPURE (NON c)) =
a E (NON b)
lo stesso per l'altra sottoformula

FORMULA SEMPLIFICATA
((NON a) E b E (NON c)) OPPURE ((NON a) E b E c)
OPPURE (a E (NON b) E (NON c)) OPPURE
(a E (NON b) E c) = ((NON a) E b) OPPURE (a E (NON b))
circuito più piccolo
problema: semplificazione "a occhio"
con 100000 variabili invece di tre?
serve:
 regole per semplificare
 e un metodo automatico

IMPLICAZIONE
altra applicazione della logica proposizionale:
effettuare ragionamenti logici

Esempio:
 Gino o sta a casa o sta al bar
 Gino non sta a casa
 conseguenza: Gino sta al bar
si esprime in logica proposizionale

MODELLI PRESI DUE VOLTE

(¬a∧b∧¬c) ∨ (a∧b∧¬c) ∨ (a∧¬b∧¬c) ∨ … =


dato che F = F∨F:

(¬a∧b∧¬c) ∨ (a∧b∧¬c) ∨ (a∧b∧¬c) ∨ (a∧¬b∧¬c) ∨ …


|------------------| |------------------|
primi due: b∧¬c
secondi due: a∧¬c

IN LOGICA
Variabili:
 casa=1 Gino sta a casa
 bar=1 Gino sta al bar

 Gino o sta a casa o sta al bar: casa ∨ bar


formule:

 Gino non sta a casa: ¬casa


 Gino sta al bar: bar

se casa ∨ bar e ¬casa allora bar


ragionamento:

IMPLICAZIONE
forma generale:
se formula, formula, … formula allora formula
per ogni valore delle variabili:
se le formule prima di "allora" valgono tutte uno
allora la formula dopo vale uno

A, B, C ⊧ Z
IMPLICAZIONE: SEMANTICA

se A=1, B=1 e C=1 allora Z=1


formalmente:
ogni interpretazione per cui A=1, B=1 e C=1 è tale per cui Z=1

COMPLESSITÀ
O-GRANDE
O-Grande esprime il costo (in termini di tempo) di un programma, e
serve per avere una stima di tempo sull'esecuzione del programma,
la notazione O non dà un tempo specifico misurato in secondi, ma
bensì una stima generale che varia a seconda dell'input così che
possiamo determinare quale tra due algoritmi sia il più efficiente.

Esempi di costi:
 20×n efficiente
 1000×n efficiente
 4×n2 un po' meno efficiente
 2n non efficiente

NOTAZIONE O: PRINCIPIO
 considerare il tempo in funzione della grandezza dell'ingresso
 prendere la parte che cresce di più
 ignorare costanti moltiplicative

45×n2+1000×n+500 ⇒
45×n2 ⇒ n2
è O(n2)

NOTAZIONE O: DEFINIZIONE
un programma ha costo (in termini di tempo) O(f(n)) se:
 il suo tempo di esecuzione è t(n) dove n è la grandezza
dell'input
 esistono due costanti a e b tali che:
t(n) < a×f(n)+b

CASO PEGGIORE
La valutazione del costo di esecuzione di un programma fa
riferimento al caso peggiore, perché ci permette di fare una stima
nel caso in cui noi fornissimo dati molto grandi.;

COSTO MEDIO
il costo medio dipende dalle probabilità esempio, x in a:
 x e gli elementi di a sono 0 o 1 probabilità indipendenti caso
medio: due passi valori interi qualsiasi sempre probabilità
indipendenti
 caso medio = caso peggiore

Potrebbero piacerti anche