<jupyter_start><jupyter_text>Basi 3 - numeri reali [Scarica zip esercizi](../_static/generated/basics.zip)[Naviga file online](https://github.com/DavidLeoni/softpython-it/tree/master/basics)**REQUISITI:**    * **Letto** [Basi 1 - variabili e interi](https://it.softpython.org/basics/basics1-ints-sol.html)* **Letto** [Basi 2 - booleani](https://it.softpython.org/basics/basics2-bools-sol.html)      Numeri realiPython salva i numeri reali (numeri in virgola mobile) in 64 bit di informazione divisi in segno, esponente e mantissa. Vediamo un esempio:<jupyter_code>3.14
type(3.14)<jupyter_output><empty_output><jupyter_text>**ATTENZIONE: bisogna usare il punto invece della virgola!**    Quindi scriverai `3.14`  invece di `3,14`    Fai molta attenzione quando copi numeri da documenti in italiano, potrebbero contenere insidiose virgole !  Notazione scientificaQuando i numeri sono molto grandi o molto piccoli, per evitare di scrivere troppi zero conviene usare la notazione scientitifica con la _e_ come $xen$, che moltiplica il numero _x_ per $10^n$Con questa notazione, in memoria vengono messe solo le cifre più significative ( _la mantissa_ ) e l'esponente, evitando quindi di sprecare spazio.<jupyter_code>75e1
75e2
75e3
75e123
75e0
75e-1
75e-2
75e-123<jupyter_output><empty_output><jupyter_text>**DOMANDA**: Guarda le seguenti espressioni, e cerca di indovinare qule risultato producono (o se danno errore):    1.  ```python    print(1.000.000)    ```1.  ```    print(3,000,000.000)    ```1.  ```python    print(2000000.000)    ```1.  ```python    print(2000000.0)    ```1.  ```python    print(0.000.123)    ```    1.  ```python    print(0.123)    ```        1.  ```python    print(0.-123)    ```            1.  ```python    print(3e0)    ```1.  ```python    print(3.0e0)    ```1.  ```python    print(7e-1)    ``` 1.  ```python    print(3.0e2)    ```1.  ```python    print(3.0e-2)    ```    1.  ```python    print(3.0-e2)    ```1.  ```python    print(4e2-4e1)    ```  Numeri troppo grandi o troppo piccoliA volte i calcoli su numeri estremamente piccoli o enormi possono produrre come risultato `math.nan` (Not a Number) o `math.inf`. Per il momento li menzioniamo e basta, trovi una discussione dettagliata nel [foglio su Numpy](https://it.softpython.org/matrices-numpy/matrices-numpy-sol.htmlNaN-e-infinit%C3%A0)  Esercizio - cerchioCalcola l'area del cerchio al centro di un pallone da calcio (raggio = 9.15m), ricordandoti che  $area= pi*r^2$ (come operatore per la potenza, usa `**`):Il tuo codice dovrebbe stampare come risultato `263.02199094102605`<jupyter_code># SOLUZIONE

r = 9.15
pi = 3.1415926536
area = pi*(r**2)
print(area)<jupyter_output>263.02199094102605<jupyter_text>Nota che le parentesi intorno al `r**2` non sono necessarie perchè l'operatore `**` ha la precedenza, ma possono aiutare la leggibilità del codice.Ricordiamo qua la precedenza degli operatori: |Operatore|Descrizione||---------|-----------||`**`|Potenza (massima precedenza)||`+` `-`| Più e meno unari||`*` `/` `//` `%`|Moltiplicazione, divisione, divisione intera, modulo||`+` `-`| Addizione e sottrazione||`` `>=`| Operatori di comparazione||`==` `!=` | Operatori di uguaglianza||`not` `or` `and`|Operatori logici (minima precedenza)|  Esercizio - frazionamentoScrivi del codice per calcolare il valore della seguente formula per `x = 0.000003`, dovresti ottenere `2.753278226511882` $$\large-\frac{\sqrt{x+3}}{\frac{(x + 2)^3}{\log{x}}}$$<jupyter_code>x = 0.000003

# scrivi qui
import math
- math.sqrt(x+3) / (((x+2)**3)/math.log(x))<jupyter_output><empty_output><jupyter_text>Esercizio - sommatoriaScrivi del codice per calcolare il valore della seguente espressione (non usare cicli, scrivi per esteso tutto i calcoli), dovresti ottenere `20.53333333333333` $$\large\sum_{j=1}^{3}{\frac{j^4}{j + 2}}$$<jupyter_code># scrivi qui
((1**4) / (1+2)) + ((2**4) / (2+2)) + ((3**4) / (3+2))<jupyter_output><empty_output><jupyter_text>Reali - conversioneSe vogliamo convertire un reale ad un intero, abbiamo a disposizione diversi modi:|Funzione|Descrizione|Simbolo matematico|Risultato||--------|-----------|------------------|---------||`math.floor(x)`| arrotonda x all'intero inferiore|$$\lfloor{8.7}\rfloor$$|8||`int(x)`| arrotonda x all'intero inferiore|$$\lfloor{8.7}\rfloor$$|8||`math.ceil(x)`| arrotonda x all'intero superiore|$$\lceil{5.3}\rceil$$|6||`round(x)`| arrotonda x all'intero più vicino|$$\lfloor{2.49}\rceil$$|2||          | |$$\lfloor{2.51}\rceil$$|3| **DOMANDA**: Guarda le espressioni seguenti, e per ciascuna cerca di indovinare quale risultato produce (o se da errore).1.  ```python    math.floor(2.3)    ```1.  ```python    math.floor(-2.3)    ```1.  ```python    round(3.49)    ```1.  ```python    round(3.51)    ```    1.  ```python    round(-3.49)    ```    1.  ```python    round(-3.51)    ```1.  ```python    math.ceil(8.1)    ```1.  ```python    math.ceil(-8.1)    ```     **DOMANDA**: Dato un qualsiasi float `x`, la seguente formula è :        ```pythonmath.floor(math.ceil(x)) == math.ceil(math.floor(x))```1. sempre `True`2. sempre `False`3. a volte `True` e a volte `False` (fornire esempi) **RISPOSTA**: la 3: per interi come `x=2.0` è `True`, negli altri casi come `x=2.3` è `False` **DOMANDA**: Dato un qualsiasi float `x`, la seguente formula è :        ```pythonmath.floor(x) == -math.ceil(-x)```1. sempre `True`2. sempre `False`3. a volte `True` e a volte `False` (fornire esempi) **RISPOSTA**: la 1.  Esercizio - tonificanteGli studi eccessivi ti hanno portato a cercare su internet ricette di bevande energetiche. Fortunatamente, una guru della nutrizione ha appena postato sul suo canale Instagram  @BeviCheTiFaBene la ricetta di un frappè portentoso:> Versare in un contenitore 2 decilitri di spremuta di kiwi, 4 decilitri di salsa di soia, e 3 decilitri di shampoo al karitè bio. Miscelare vigorosamente e poi versare metà del composto in un bicchiere. Rabboccare il bicchiere fino al decilitro intero superiore. Tracannare avidamente.Corri a comprare gli ingredienti, e ti appresti a miscelarli. Hai a disposizione un misurino in cui travasi i preziosi fluidi, ad uno ad uno. Nell'effettuare il travaso, versi sempre un po' più del necessario (ma mai più di 1 decilitro), e ad ogni ingrediente elimini poi l'eccesso.* **NON** usare sottrazioni, prova ad usare solo gli operatori per gli arrotondamenti Esempio:Dati```pythonkiwi = 2.4soia = 4.8shampoo = 3.1misurino = 0.0mixer = 0bicchiere = 0.0```Il tuo codice deve stampare:```Verso nel misurino 2.4 dl di kiwi, tolgo eccesso fino a tenere 2 dlTravaso nel mixer, adesso contiene 2 dlVerso nel misurino 4.8 dl di soia, tolgo eccesso fino a tenere 4 dlTravaso nel mixer, adesso contiene 6 dlVerso nel misurino 3.1 dl di shampoo, tolgo eccesso fino a tenere 3 dlTravaso nel mixer, adesso contiene 9 dlVerso metà della miscela ( 4.5 dl ) nel bicchiereRabbocco il bicchiere fino al decilitro intero superiore, adesso contiene 5 dl```<jupyter_code>kiwi = 2.4
soia = 4.8
shampoo = 3.1
misurino = 0.0
mixer = 0.0
bicchiere = 0.0


# scrivi qui
print('Verso nel misurino', kiwi, 'dl di kiwi, tolgo eccesso fino a tenere', int(kiwi), 'dl')
mixer += int(kiwi)
print('Travaso nel mixer, adesso contiene', mixer, 'dl')
print('Verso nel misurino', soia, 'dl di soia, tolgo eccesso fino a tenere', int(soia), 'dl')
mixer += int(soia)
print('Travaso nel mixer, adesso contiene', mixer, 'dl')
print('Verso nel misurino', shampoo, 'dl di shampoo, tolgo eccesso fino a tenere', int(shampoo), 'dl') 
mixer += int(shampoo)
print('Travaso nel mixer, adesso contiene', mixer, 'dl')
bicchiere = mixer/2
print('Verso metà della miscela (', bicchiere, 'dl ) nel bicchiere')
print('Rabbocco il bicchiere fino al decilitro intero superiore, adesso contiene:', math.ceil(bicchiere), 'dl')<jupyter_output>Verso nel misurino 2.4 dl di kiwi, tolgo eccesso fino a tenere 2 dl
Travaso nel mixer, adesso contiene 2.0 dl
Verso nel misurino 4.8 dl di soia, tolgo eccesso fino a tenere 4 dl
Travaso nel mixer, adesso contiene 6.0 dl
Verso nel misurino 3.1 dl di shampoo, tolgo eccesso fino a tenere 3 dl
Travaso nel mixer, adesso contiene 9.0 dl
Verso metà della miscela ( 4.5 dl ) nel bicchiere
Rabbocco il bicchiere fino al decilitro intero superiore, adesso contiene: 5 dl<jupyter_text>Esercizio - arrotondamenteScrivi del codice per calcolare il valore della seguente formula per `x = -5.51`, dovresti ottenere `41`$$\large\lvert{\lceil{x}\rceil}\rvert + \lfloor{x}\rceil^2$$<jupyter_code>import math 

x = -5.51   # 41
#x = -5.49  # 30

# scrivi qui
abs(math.ceil(x)) + round(x)**2<jupyter_output><empty_output><jupyter_text>Reali - uguaglianza    **ATTENZIONE: Ciò che segue vale per** ***tutti*** **i linguaggi di programmazione!**     Alcuni risultati ti parranno curiosi ma è il modo in cui la maggior parte dei processori (CPU) opera, indipendentemente da Python.Quando si effettuano calcoli con i numeri in virgola mobile, il processore può commettere degli errori di arrotondamento dovuto ai limiti della rappresentazione interna. Sotto il cofano i numeri float vengono memorizzati in una sequenza in codice binario di 64 bit, secondo lo standard _IEEE-754 floating point arithmetic_ : questo impone un limite fisico alla precisione dei numeri, e a volte possono anche capitare sorpese dovute alla conversione da decimale a binario. Per esempio, proviamo a stampare `4.1`:<jupyter_code>print(4.1)<jupyter_output>4.1<jupyter_text>Per nostra convenienza Python ci mostra `4.1`, ma in realtà nella memoria del processore è finito un numero diverso ! Quale? Per scoprire cosa nasconde, con `format` possiamo esplicitamente formattare il numero con lo specificatore di formato `f` usando per esempio `55` cifre di precisione:<jupyter_code>format(4.1, '.55f')<jupyter_output><empty_output><jupyter_text>Possiamo quindi chiederci quale potrà essere il risultato di un calcolo:<jupyter_code>print(7.9 - 3.8)<jupyter_output>4.1000000000000005<jupyter_text>Notiamo che il risultato è ancora diverso da quello atteso ! Indagando meglio, notiamo che Python non ci sta nemmeno mostrando tutte le cifre:<jupyter_code>format(7.9 - 3.8, '.55f')<jupyter_output><empty_output><jupyter_text>E se volessimo sapere se due calcoli coi float producono lo 'stesso' risultato?**ATTENZIONE: EVITA IL** `==` **CON I FLOAT!**       Per capire  se il risultato tra due calcoli con i float è uguale, **NON** puoi usare l'operatore `==`:<jupyter_code>7.9 - 3.8 == 4.1    # GUAI IN VISTA !<jupyter_output><empty_output><jupyter_text>Invece, devi preferire alternative che valutano se un numero float è _vicino_ ad un altro, come per esempio la comoda funzione [math.isclose](https://docs.python.org/3/library/math.htmlmath.isclose):<jupyter_code>import math

math.isclose(7.9 - 3.8, 4.1)   # MOLTO MEGLIO<jupyter_output><empty_output><jupyter_text>Di default `math.isclose` usa una precisione di `1e-09` ma volendo, a `math.isclose` puoi anche passare un limite di tolleranza entro la quale deve essere la differenza tra i due numeri affinchè siano considerati uguali:<jupyter_code>math.isclose(7.9 - 3.8, 4.1, abs_tol=0.000001)<jupyter_output><empty_output><jupyter_text>**DOMANDA**: Possiamo rappresentare perfettamente il numero $\sqrt{2}$ in un `float`? **RISPOSTA**: $\sqrt{2}$ è irrazionale e pertanto non possiamo sperare di rappresentarlo perfettamente, qualunque calcolo useremo per ottenerlo avrà sempre un certo grado di imprecisione. **DOMANDA**: Quali di queste tre espressioni di codice danno lo stesso risultato?```python    import mathprint('a)', math.sqrt(3)**2 == 3.0)print('b)', abs(math.sqrt(3)**2 - 3.0) < 0.0000001)print('c)', math.isclose(math.sqrt(3)**2, 3.0, abs_tol=0.0000001))``` **RISPOSTA**: la b) e la c) danno `True`. La a) da `False`, perchè durante i calcoli in virgola mobile  vengono compiuti errori di arrotondamento.  Esercizio - quadraticaScrivi del codice che calcola gli zero dell'equazione $ax^2-b = 0$ - Mostra i numeri con **20 cifre** di precisione- Alla fine controlla che sostituendo il valore ottenuto di `x` nell'equazione si ottenga effettivamente zero. Esempio - dati:```pythona = 11.0b = 3.3```dopo il tuo codice deve stampare:```11.0 * x**2 - 3.3 = 0  per x1 = 0.5477225575051660744211.0 * x**2 - 3.3 = 0  per x2 = -0.547722557505166074420.54772255750516607442 è una soluzione? True-0.54772255750516607442 è una soluzione? True```<jupyter_code>a = 11.0
b = 3.3  

# scrivi qui

import math

x1 = math.sqrt(b/a)
x2 = -math.sqrt(b/a)

print(a, "* x**2 -",b,"= 0  per x1 =", format(x1, '.20f'))
print(a, "* x**2 -",b,"= 0  per x2 =", format(x2, '.20f'))

# abbiamo bisogno di cambiare il valore di default di tolleranza
print(format(x1, '.20f'), "è una soluzione?", math.isclose(a*(x1**2) - b,0, abs_tol=0.00001))
print(format(x2, '.20f'), "è una soluzione?", math.isclose(a*((x2)**2) - b,0, abs_tol=0.00001))<jupyter_output>11.0 * x**2 - 3.3 = 0  per x1 = 0.54772255750516607442
11.0 * x**2 - 3.3 = 0  per x2 = -0.54772255750516607442
0.54772255750516607442 è una soluzione? True
-0.54772255750516607442 è una soluzione? True<jupyter_text>Esercizio - alla modaStai già pensando alle prossime vacanze, ma c'è un problema: dove vai, se un _selfie-stick_ non ce l'hai? Non puoi partire con questo grave turbamento: per uniformarti al fenomeno di massa devi comprare lo stick più simile agli altri. Conduci quindi prima un'indagine statistica tra turisti malati di selfie-stick con l'obiettivo di scoprire i brand più frequenti, in altre parole, la _moda_ delle frequenze. Ottieni questi risultati:<jupyter_code>b1,b2,b3,b4,b5 = 'TroppiLike', 'ErMejo United', 'Perditempo SpA', 'Vanità 3.0','TronistiPerCaso' # brand
f1,f2,f3,f4,f5 = 0.25, 0.3, 0.1, 0.05, 0.3   # frequenze (in percentuale)<jupyter_output><empty_output><jupyter_text>Desumiamo quindi che le masse prediligono i selfie-stick dei brand `'ErMejo United'` e `'TronistiPerCaso'`, entrambi a parimerito con un 30% di turisti ciascuno. Scrivi quindi del codice che stampa questo risultato:```TroppiLike è il più frequente? False ( 25.0 % )ErMejo United è il più frequente? True ( 30.0 % )Perditempo Inc è il più frequente? False ( 10.0 % )Vanità 3.0 è il più frequente? False ( 5.0 % )TronistiPerCaso è il più frequente? True ( 30.0 % )```* **ATTENZIONE**: il tuo codice deve funzionare con **QUALUNQUE** serie di variabili !!<jupyter_code>b1,b2,b3,b4,b5 = 'TroppiLike', 'ErMejo United', 'Perditempo Inc', 'Vanità 3.0','TronistiPerCaso'    # brand
f1,f2,f3,f4,f5 = 0.25, 0.3, 0.1, 0.05, 0.3         # frequenze (in percentuale)  False True False False True
# OCCHIO, sembrano uguali ma deve funzionare anche con queste ;-)
#f1,f2,f3,f4,f5 = 0.25, 0.3, 0.1, 0.05, 0.1 + 0.2  #  False True False False True
                                        
# scrivi qui
mx = max(f1,f2,f3,f4,f5)
print(b1, 'è il più frequente?', math.isclose(f1,mx), '(', f1*100.0, '% )')
print(b2, 'è il più frequente?', math.isclose(f2,mx), '(', f2*100.0, '% )')
print(b3, 'è il più frequente?', math.isclose(f3,mx), '(', f3*100.0, '% )')
print(b4, 'è il più frequente?', math.isclose(f4,mx), '(', f4*100.0, '% )')
print(b5, 'è il più frequente?', math.isclose(f5,mx), '(', f5*100.0, '% )')<jupyter_output>TroppiLike è il più frequente? False ( 25.0 % )
ErMejo United è il più frequente? True ( 30.0 % )
Perditempo Inc è il più frequente? False ( 10.0 % )
Vanità 3.0 è il più frequente? False ( 5.0 % )
TronistiPerCaso è il più frequente? True ( 30.0 % )<jupyter_text>Numeri decimaliPer moltissime applicazioni i `float` sono sufficienti, avendo coscienza dei loro limiti di rappresentazione e uguaglianza. Se proprio hai bisogno di maggiore precisione e/o prevedibilità, Python offre un tipo numerico apposito chiamato `Decimal`, che permette una precisione arbitraria. Per usarlo, devi prima importarlo dalla libreria `decimal`:<jupyter_code>from decimal import Decimal<jupyter_output><empty_output><jupyter_text>Possiamo creare un `Decimal` a partire da una stringa:<jupyter_code>Decimal('4.1')<jupyter_output><empty_output><jupyter_text>**ATTENZIONE: se crei un Decimal a partire da una costante, indicala come stringa!**    Se gli passi un `float` rischi di perdere l'utilità dei Decimal:<jupyter_code>Decimal(4.1)  # così mi ritrovo coi problemi dei float ...<jupyter_output><empty_output><jupyter_text>Operazioni tra `Decimal` producono altri `Decimal`:<jupyter_code>Decimal('7.9') - Decimal('3.8')<jupyter_output><empty_output><jupyter_text>Questa volta, possiamo tranquillamente usare l'operatore di uguaglianza e ottenere il risultato atteso:<jupyter_code>Decimal('4.1') == Decimal('7.9') - Decimal('3.8')<jupyter_output><empty_output><jupyter_text>Sono anche supportate alcune funzioni matematiche, e spesso si comportano in modo più predicibile (nota che **non** stiamo usando `math.sqrt`):<jupyter_code>Decimal('2').sqrt()<jupyter_output><empty_output><jupyter_text>**Ricordati comunque che la memoria del computer è finita!**I Decimal non possono essere la panacea per tutti i mali: per es, $\sqrt{2}$ non ci starà mai completamente nella memoria di nessun computer ! Possiamo verificare le limitazioni elevando al quadrato il risultato:<jupyter_code>Decimal('2').sqrt()**Decimal('2')<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.1319796954314721, 'fraction_numerical': 0.052978586848707626, 'mean_word_length': 4.833900612661675, 'pattern_counts': {'":': 0, '<': 92, '<?xml version=': 0, '>': 93, 'https://': 5, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 2, 'word_list_counts': {'cursed_substrings.json': 1, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '24', 'dir': 'jupyter-structured-clean-dedup', 'id': '465372', 'license': 'CC-BY-4.0', 'n_tokens_mistral': 7073, 'n_tokens_neox': 6603, 'n_words': 1919, 'path': 'basics/basics3-floats-sol.ipynb', 'repo_name': 'DavidLeoni/softpython-', 'size': '17139'}