Numeri grossi –troppo!

Una scorsa ai linguaggi –non di sistema— per un presunto problema, quello evidenziato qui.

Uh! verifiche, prima di subito! 💥

bc
Anticamente, quando il  mondo  Unix era giovane si usava bc; OK, prima ancora c’era dc ma –come dire…

* bigN $ bc -l
a = 57055^3
b = 339590^3
c = 340126^3
a + b
39347712995520375
c
39347712995520376
(a + b) == c
0

OK, al solito per i valori booleani false viene rappresentato da 0.

Calc
Ma l’evoluzione… bc è sempre OK, ce l’ho nel mio toolbox ma normalmente per queste elaborazioni volanti uso Calc.

* bigN $ calc -d
; a = 57055**3
; b = 339590**3
; c = 340126**3
; a + b
	39347712995520375
; c
	39347712995520376
; (a + b) == c
	0

Python
Abitualmente sono pythonista

* bigN $ python3 -q
>>> a = 57055**3
>>> b = 339590**3
>>> c = 340126**3
>>> a + b
39347712995520375
>>> c
39347712995520376
>>> (a + b) == c
False

Racket
Quando posso (cioè è solo per me, nessuno che poi mi urla dietro) faccio così:

* bigN $ racket
Welcome to Racket v6.9.
> (define a (expt 57055 3))
> (define b (expt 339590 3))
> (define c (expt 340126 3))
> (+ a b)
39347712995520375
> c
39347712995520376
> (= (+ a b) c)
#f

newLISP
Un Lisp ruspante, piccolo, veloce –posso dire quirkxotico?– che amo da sempre.

> (set 'a (pow 57055 3))
185729602441375
> (set 'b (pow 339590 3))
3,9161983393079e+16
> (set 'c (pow 340126 3))
3,934771299552038e+16
> (+ a b)
39347712995520375
> (- c (+ a b))
1
> (= c (+ a b))
true

Ahemmm… no! vede che c’è la differenza di 1 ma la comparazione con = da true.

Ma sono io che sto sbagliando! Leggi il manuale! (cit.) 👿

> (set 'a (pow (bigint 57055) 3))
185729602441375
> (set 'b (pow (bigint 339590) 3))
3,9161983393079e+16
> (set 'c (pow (bigint 340126) 3))
3,934771299552038e+16
> (+ a b)
39347712995520375
> (= c (+ a b))
true
> (zero? (- c (+ a b)))
nil
> (- c (+ a b))
1

Non funziona la funzione = (che però si può facilmente ridefinire) ma i calcoli sono corretti.

Posso non provare SmallTalk? devo vero? Ecco:

* bigN $ gst
GNU Smalltalk ready

st> a := 57055 raisedToInteger: 3.
185729602441375
st> b := 339590 raisedToInteger: 3.
39161983393079000
st> c := 340126 raisedToInteger: 3.
39347712995520376
st> a + b
39347712995520375
st> (a + b) == c
false

Foglio di calcolo, tipo Excel
C’è anche chi… OK, provo. Non posso copiare come vorrei (come fatto finora) il testo, metto lo screenshot.
Personalmente: detesto la sintassi tutta sua, ma forse basta abituarsi.

Ah! ero partito da qui, mica l’ho dimenticato.

JavaScript

st> * bigN $ node
> a = Math.pow(57055, 3)
185729602441375
> b = Math.pow(339590, 3)
39161983393079000
> c = Math.pow(340126, 3)
39347712995520376
> (a + b) == c
true
> (a + b) - c
0

No!, sbaglia anche la sottrazione.

Insomma solo i linguaggi che supportano la precisione arbitraria per gli interi sono matematicamente corretti.

In pratica serve tutta questa precisione? Dipende, ma in genere no.

Mi dicono, ma non ho verificato, che anche per JavaScript esiste un modulo ad hoc.

Gli altri linguaggi? Sì, per esempio Julia, Ruby e Lua, c’è per tutti tre. Si potrebbe provarli ma credo basti. O no? 😐

👽

Posta un commento o usa questo indirizzo per il trackback.

Rispondi

Inserisci i tuoi dati qui sotto o clicca su un'icona per effettuare l'accesso:

Logo WordPress.com

Stai commentando usando il tuo account WordPress.com. Chiudi sessione /  Modifica )

Google+ photo

Stai commentando usando il tuo account Google+. Chiudi sessione /  Modifica )

Foto Twitter

Stai commentando usando il tuo account Twitter. Chiudi sessione /  Modifica )

Foto di Facebook

Stai commentando usando il tuo account Facebook. Chiudi sessione /  Modifica )

Connessione a %s...

This site uses Akismet to reduce spam. Learn how your comment data is processed.

%d blogger hanno fatto clic su Mi Piace per questo: