lunedì 30 maggio 2011

A volte i computer non ce la fanno — 1

Spesso si pensa che i computer abbiano risolto tutti i nostri problemi di calcolo. Se i numeri sono troppo grandi, ci pensa lui (o la calcolatrice). Non è proprio così.

Ogni tanto faccio notare agli studenti che, quando calcolano 1/3 e poi rimoltiplicano il risultato per 3, ottengono come risultato 1 perché la calcolatrice sbaglia due volte.

Sbaglia una prima volta perché 1/3 dovrebbe dare, come risultato, 0 seguito da infinite cifre 3, mentre il display ne mostra solo un certo numero. Sbaglia una seconda volta perché se moltiplichiamo quel risultato per 3, il risultato dovrebbe essere uno 0 seguito da un certo numero di 9.

Qualche calcolatrice moderna potrebbe, in effetti, memorizzare le frazioni in modo esatto (almeno frazioni semplici come 1/3), ma lo stesso problema si presenta quando si digita 2, poi si fa la radice quadrata, e successivamente il quadrato. Il risultato non dovrebbe essere 2, a rigore.

Come mai allora otteniamo il risultato giusto? Si tratta di un trucco: la calcolatrice ha una memoria capace di memorizzare n cifre, ma ce ne fa vedere meno, diciamo n-3. Allora quando calcoliamo 1/3 il risultato è 0 seguito da n-1 cifre 3 (diciamo n-1 perché una di queste cifre è occupata dallo 0 iniziale, poi potrebbe non essere così, ma facciamo finta), ma il sistema approssima il risultato facendoci vedere solo n-4 cifre uguali a 3.

Quando rimoltiplichiamo per 3, il risultato sarebbe 0 seguito da n-1 cifre 9, che, approssimato a n-4 cifre, diventa 1. Due approssimazioni producono il risultato giusto.

Non funziona sempre, però.

12 commenti:

epsilon_macchina ha detto...

a volte certe calcolatrici memorizzano oltre al risultato , l'espressione che valutata porta ad esso.
un riutilizzo di quel risultato, per la calcolatrice in questione significa riprendere l'espressione, modificarla e ri-valutarla proprio all'ultimo.
cosi ci si evita, per quanto possibile, gli orrori di arrotondamento e/o troncamento..

.mau. ha detto...

più che altro le calcolatrici lavorano con più cifre decimali di quante poi mostrino, e [quelli che hanno programmato i loro algoritmi interni] sperano che gli errori di arrotondamento non si propaghino troppo.

zar ha detto...

Adesso ci sono calcolatrici moderne che riescono a memorizzare frazioni in modo esatto, e usano precisione "infinita". In quel caso, 1 diviso 3 per 3 fa 1 senza problemi. Io facevo l'esempio delle calcolatrici che lavorano in decimale.

(La mia bellissima calcolatrice memorizza correttamente anche le radici, però)

juhan ha detto...

Credo che ci farò un post, per intanto un piccolo assaggino, con Python e newLISP

* : _da_proc_1_ $ python
Python 2.6.6 (r266:84292, Sep 15 2010, 15:52:39)
[GCC 4.4.5] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> un_terzo = 1./3
>>> un_terzo
0.33333333333333331
>>> uno = un_terzo * 3
>>> uno
1.0
>>> import math
>>> rad_2 = math.sqrt(2)
>>> rad_2
1.4142135623730951
>>> due = rad_2 * rad_2
>>> due
2.0000000000000004
>>> dueq = rad_2 ** 2
>>> dueq
2.0000000000000004
>>>

* : _da_proc_1_ $ newlisp
newLISP v.10.2.8 on Linux IPv4 UTF-8, execute 'newlisp -h' for more info.

> (set 'un_terzo (div 1,0 3,0))
0,3333333333
> (set 'uno (mul un_terzo 3))
1
> (set 'rad_2 (sqrt 2,0))
1,414213562
> (set 'due (mul rad_2 rad_2))
2
> (set 'dueq (pow rad_2 2))
2
> * : _da_proc_1_ $

zar ha detto...

Ahia, python mi delude...

juhan ha detto...

Perché? Per un ing. o un inf. (ormatico) va bene; mica tutti sono come i matematti!
Uno di questi giorni pubblico il test per un po' di linguaggi. Il problema era molto sentito una volta (20-40 anni fa) con il Fortran. Io l'ho rivisto affrontare recentemente dal team di Scilab (ne parlo nel blog ma sono troppo stanco per mettere il link).

zar ha detto...

Bé, lisp dice che il quadrato di radice di 2 è 2, mentre python dice che è 2 e un po', non va bene...

.mau. ha detto...

lo spero bene che LISP queste cose le sappia fare :-)

zar ha detto...

cos'ha di più lisp rispetto a python?

.mau. ha detto...

credo che LISP faccia un bel po' di conti simbolici, almeno da quello che ricordo fumosamente...

zar ha detto...

Ah, così di base? Bello.

pabell ha detto...

Occhio, che dipende anche da come python stampa a video i risultati. Infatti, se usi la funzione "print":

>>> un_terzo = 1./3
>>> un_terzo
0.33333333333333331
>>> print un_terzo
0.333333333333
>>> import math
>>> rad_2 = math.sqrt(2)
>>> rad_2
1.4142135623730951
>>> due = rad_2 * rad_2
>>> due
2.0000000000000004
>>> print due
2.0