Python: Numeri¶
Numeri: Tipi Fondamentali¶
Ci sono tre tipi numerici fondamentali:
Tipo | Significato |
---|---|
int |
Rappresenta numeri interi (!) |
float |
Rappresenta numeri razionali a virgola mobile (float ing-point) |
bool |
Rappresenta condizioni, puo’ essere True o False |
Note
I razionali float
hanno precisione limitata: la maggior parte dei
razionali puo’ essere rappresentata solo approssimatamente con un
float
.
Ai fini di questo corso, i dettagli non sono importanti.
Esempio. Creo tre variabili, una per tipo, poi le stampo a schermo con
print
:
n = 10
x = 3.14
cond = False
# Stampo le tre variabili
print(n, x, cond)
# Idem, inframezzando testo
print("n =", n, "x =", x, "e la condizione cond vale", cond)
Questa sintassi di print
vale per tutti i tipi di variabili, non solo
quelli numerici.
Numeri: Aritmetica¶
Tutti i tipi numerici mettono a disposizione le stesse operazioni aritmetiche:
Operazione | Significato |
---|---|
a + b |
somma |
a - b |
differenza |
a * b |
prodotto |
a / b |
divisione |
a // b |
divisione intera |
a % b |
resto della divisione (o modulo) |
a ** b |
elevamento a potenza |
Il tipo del risultato di n operazione m
e’ automaticamente il tipo
piu’ “complesso” tra i tipi di n
e m
– per questo si parla di
conversione automatica.
La scala di complessita’ dei tipi numerici e’:
bool < int < float
Esempio. Ad esempio, se sommo un int
ed un float
, otterro’ un
float
:
risultato = 1.2 + 1 # float * int
print(risultato) # 1.2
print(type(risultato)) # float
Questo perche’ e’ necessario un float
per rappresentare il valore 1.2
:
un int
non basterebbe!
Warning
Per evitare errori, e’ necessario scegliere il tipo delle variabili in modo che il tipo del risultato sia sufficientemente “complesso” da riuscire a rappresentarne il valore.
Numeri: Confronti¶
Tutti i tipi numerici (e in generale tutto i tipi Python che vedremo durante il corso) supportano le operazioni di comparazione:
Operazione | Significato |
---|---|
a == b |
uguale |
a != b |
diverso |
a < b |
minore |
a <= b |
minore o uguale |
a > b |
maggiore |
a >= b |
maggiore o uguale |
Il risultato di un’espressione di confronto e’ sempre un bool
: vale
True
se la condizione e’ soddisfatta, e False
altrimenti.
Esempio. Aritmetica e confronti possono essere combinati per verificare condizioni “complesse”, come questa:
na, nc, ng, nt = 2, 6, 50, 4
risultato = (na + nt) > (nc + ng)
print(risultato)
print(type(risultato))
I valori Booleani bool
(es. i risultati delle operazioni di confronto)
possono essere combinati attraverso le operazioni logiche:
Operazione | Significato |
---|---|
a and b |
congiunzione: True se e solo se a e b sono True |
a or b |
disgiunzione: True se almeno una tra a e b e’ True |
not a |
negazione: True se a e’ False e viceversa |
Qui sia a
che b
sono dei bool
.
Warning
In generale, fare aritmetica (es. somme) con valori Booleani e costruire espressioni logiche con valori interi o razionali e’ sconsigliato.
In questi casi, Python si comporta in modo (deterministico e spiegabile, ma decisamente) bizzarro.
Esempio. x > 12
e x < 34
danno come risultato dei bool
, quindi
le posso combinare per ottenere:
# int int
# | |
print((x > 12) and (x < 34))
# \______/ \______/
# bool bool
# \___________________/
# bool
oppure:
# int int
# | |
print((not (x > 12)) or (x < 34))
# \______/
# bool
# \____________/ \______/
# bool bool
# \________________________/
# bool
Esempi¶
Esempio. Calcolo gli zeri dell’equazione quadratica x^2 - 1 = 0:
a, b, c = 1.0, 0.0, -1.0
delta = b**2 - 4*a*c
zero1 = (-b + delta**0.5) / (2 * a)
zero2 = (-b - delta**0.5) / (2 * a)
print(zero1, zero2)
Qui uso x**0.5
per calcolare la radice quadrata: \sqrt{x} = x^\frac{1}{2}.
Esempio. Voglio calcolare il GC-content di un gene. So che il gene:
- E’ lungo 1521 basi.
- Contiene 316 citosine.
- Contiene 235 guanine.
Simbolicamente, il GC-content e’ definito come (g + c) / n. Per calcolarlo posso scrivere:
n, c, g = 1521, 316, 235
gc_content = (c + g) / n
print(gc_content)
Esempio. Per controllare che x
(il cui valore e’ “fuori dal mio
controllo”, ma nell’esempio sotto fisso per convenienza) cada nell’intervallo A
= [10,50] scrivo:
x = 17 # ad esempio
minimo_a, massimo_a, x = 10, 50
dentro_a = (minimo_a <= x <= massimo_a)
print(dentro_a)
oppure:
dentro_a = ((x >= minimo_a) and (x <= massimo_a))
Assumendo che dentro_a
, dentro_b
e dentro_c
indichino che x
e’
nell’intervallo A, B o C, rispettivamente, posso comporre condizioni piu’
complesse:
# x e' in almeno uno dei tre intervalli
dentro_almeno_uno = dentro_a or dentro_b or dentro_c
# x e' sia in A e B, ma non in C
dentro_a_e_b_ma_non_c = dentro_a and dentro_b and (not dentro_c)
Esercizi¶
Creare alcune variabili, controllando ad ogni passaggio che valore e tipo siano corretti (usando
print
etype
):a
eb
con valore12
e23
come interi.x
ey
con valore21
e14
come razionali.
Usando
print
(una sola volta), stampare:- Tutte le variabili di cui sopra sulla stessa riga.
- Tutte le variabili di cui sopra, separate da
;
, sulla stessa riga. - Il testo “il prodotto di
a
eb
e’a * b
”, sostituendo ada
,b
ea * b
i valori delle variabili.
Determinare valore e tipo di:
- Il prodotto di
a
eb
. - Il quoziente di
x
ey
. - Il quoziente intero di
a
eb
. - Il quoziente intero di
x
ey
. - Il prodotto di
b
ey
. 2
elevato a0
.2
elevato a1.2
.2
elevato a-2
.- La radice quadrata di
4
. - La radice quadrata di
2
.
- Il prodotto di
Che differenza c’e’ tra:
10 / 12
10 / 12.0
10 // 12
10 // 12.0
Che differenza c’e’ tra:
10 % 3
10 % 3.0
Usando
pi = 3.141592
e dator = 2.5
, calcolare:- La circonferenza di raggio
r
: 2 \pi r. - L’area di un cerchio di raggio
r
: \pi r^2. - Il volume di una sfera di raggio
r
: \frac{4}{3} \pi r^3.
- La circonferenza di raggio
Creare due variabili
a = 100
eb = True
. Usando un numero opportuno di variabili ausiliarie (chiamatele come volete!), fate in modo che il valore dia
finisca inb
e che quello dib
finisca ina
.(Scrivere
a = True
eb = 100
non vale!)Si puo’ fare con una sola variabile ausiliaria?
Sullo stesso strand di DNA si trovano due geni. Il primo include i nucelotidi dalla posizione 10 alla posizione 20, il secondo quelli dalla posizione 30 alla posizione 40. Scriviamo queste informazioni cosi’:
gene1_inizio, gene1_fine = 10, 20 gene2_inizio, gene2_fine = 30, 40
Data una variabile
pos
che rappresenta una posizione arbitraria sullo strand, scrivere dei confronti per verificare se:pos
si trova nel primo gene.pos
si trova nel secondo gene.pos
si trova tra l’inizio del primo gene e la fine del secondo.pos
si trova tra l’inizio del primo gene e la fine del secondo, ma in nessuno dei due geni.pos
si trova prima dell’inizio del primo gene o dopo la fine del secondo.pos
cade in uno dei due geni.pos
non dista piu’ di 10 dall’inizio del primo gene.
Date le tre variabili Booleane
t
,u
, ev
, scrivere delle espressioni che valgonoTrue
se e solo se:t
,u
,v
tutte e tre vere.t
e’ vera oppureu
e’ vera, ma non entrambe.- Esattamente una delle tre variabili e’ falsa.
- Esattamente una delle tre variabili e’ vera.
Soluzioni¶
Soluzioni:
a = 12 b = 23 print(a, b) print(type(a), type(b)) # int, int x = 21.0 y = 14. print(x, y) print(type(x), type(y)) # float, float
Soluzioni:
print(a, b, x, y) print(a, ";", b, ";", x, ";", ...)
Soluzioni:
# casi semplici: prodotto = a * b # int * int print(prodotto) print(type(prodotto)) # int # divisione e divisione intera tra vari # tipi di numeri: quoziente = x / y # float / float print(quoziente) print(type(quoziente)) # float risultato = a // b # int // int print(risultato) print(type(risultato)) # int risultato = x // y # float // float print(risultato) print(type(risultato)) # float risultato = b * y # int * float print(risultato) print(type(risultato)) # float # qui il tipo e' determinato automaticamente # in base alla magnitudine del risultato: risultato = 2**0 # int**int print(risultato) print(type(risultato)) # int risultato = 2**1.2 # int*float print(risultato) print(type(risultato)) # float risultato = 2**-2 # int*int print(risultato) print(type(risultato)) # *** float!!! *** risultato = 4**0.5 # int*float print(risultato) print(type(risultato)) # float risultato = 2**0.5 # int*float print(risultato) print(type(risultato)) # float
Soluzioni:
>>> print(10 / 12) 0.8333333333333334 >>> print(10 / 12.0) 0.8333333333333334 >>> print(10 // 12) 0 >>> print(10 // 12.0) 0.0
Come si vede la divisione intera si comporta normalmente rispetto ai tipi: quando la applico ai due float il risultato e’ quello della divisione normale, ma troncato all’intero
0
.Soluzioni:
>>> 10 % 3 1 >>> 10 % 3.0 1.0
Come si puo’ vedere,
%
ritorna il resto di10 / 3
:10 = 3*3 + 1 # ^ # il resto
Il tipo degli operandi non influenza il valore del risultato, solo il suo tipo.
Soluzione:
pi = 3.141592 r = 2.5 circonferenza = 2 * pi * r print(circonferenza) area = 2 * pi * r**2 print(area) area = 2 * pi * r * r print(area) volume = (4.0 / 3.0) * pi * r**3 print(volume)
Soluzione:
a, b = 100, True a2 = a b2 = b b = a2 a = b2 print(a, b)
oppure:
a, b = 100, True x = a a = b b = x print(a, b)
Soluzione:
gene1_inizio, gene1_fine = 10, 20 gene2_inizio, gene2_fine = 30, 40 # disegnino: # # 5' 3' # ~~~~~xxxxxxxx~~~~~xxxxxxx~~~~~> # 10 20 30 40 # \______/ \_____/ # gene_1 gene_2 # due alternative condizione_1 = (10 <= pos <= 20) condizione_1 = (pos >= 10 and pos <= 20) condizione_2 = (30 <= pos <= 40) condizione_3 = (10 <= pos <= 40) # due alternative condizione_4 = condizione_3 and not (condizione_1 or condizione_2) condizione_4 = (20 <= pos <= 40) condizione_5 = pos < 10 or pos > 40 # occhio che: # # pos < 10 and pos > 40 # # non ha senso: e' sempre False! condizione_6 = condizione_1 or condizione_2 condizione_7 = (0 <= pos <= 20)
Il codice va testato con diversi valori di
posizione
, in modo da controllare che le condizioni si comportino come vogliamo: che sianoTrue
quando la posizione soddisfa i requisiti della domanda, eFalse
altrimenti.Soluzione:
tutte_e_tre = t and u and v t_oppure_u_ma_non_tutte_e_due = (t or u) and not (t and u) # NOTA: qui i backslash alla fine delle righe servono # per andare "a capo", potete ignorarli. una_delle_tre_falsa = \ (t and u and not v) or \ (t and not u and v) or \ (not t and u and v) una_delle_tre_vera = \ (t and not u and not v) or \ (not t and u and not v) or \ (not t and not u and v)
Di nuovo, il codice va testato usando diversi valori per
t
,u
ev
. Ci sono 8 combinazioni in tutto:t, u, v = False, False, False t, u, v = False, False, True t, u, v = False, True, False t, u, v = False, True, True # ...