Newsgroup: it.comp.lang.javascript
Titolo: Occhio ai bit!

Proseguo da solo una sempiterna discussione.
Capita talvolta leggere messaggi di persone che lamentano bug
nell'interprete javascript/jscript a causa dei risultati di operazioni come
4.97-4 che non restituiscono il valore desiderato.
Piu' volte si e' spiegato che non e' un bug ma un comportamento dell'engine
causato da bit residui nei calcoli in virgola mobile. I comportamenti
variano con diversi linguaggi, ma il problema puo' persistere (VBScript, ad
esempio, risponde esattamente in questo caso specifico, ma si comporta
similmente con altre operazioni).
Casi come questo sono facili da controllare e prevedere, ma e' bene fare
attenzione alle casistiche.
Torno a parlare del linguaggio che a noi piace tanto.
var a = Math.pow(10,16);
ovviamente a==10000000000000000;
se ora facciamo un banale a++ e chiediamo a js di visualizzare il valore
noteremo che il risultato e' INVARIATO.
Da notare che a questo punto js risponde true alle seguenti espressioni:
10000000000000000==a
10000000000000001==a
Altro punto interessante: a*2 ==20000000000000000
(che per js e' tra l'altro uguale sia a 20000000000000000 che a
20000000000000001)
Mentre a<<1 (shift sinistro "equivalente" ad una moltiplicazione per 2)
== -545128448 (NEGATIVO)
Ho usato 10^16 proprio per superare 10^15 che inteso come numero binario e',
guarda caso, 32768.
Puo' essere significativa la "coincidenza" per capire come lavora l'engine?
Riproducendo gli esempi precedenti con 10^15 sui calcoli decimali abbiamo i
risultati sperati, usando shift binari, tuttavia, no.
La nona potenza di 10 e' l'ultima a restituire con uno shift sinistro (ma di
una sola posizione) il risultato decimale che ci aspettiamo.
Aspetto considerazioni, tanto se conosco bene Zer0 (prima cifra binaria),
arriveranno veloci fulmini e roboanti come tuoni...

 ha
scritto:
Non e' ne' un bug, ne' un comportamento dell'engine quanto del processore
stesso (ALU o qualunque cosa si dedichi a tali operazioni in JS nei
processori odierni), in quanto tutto deve essere riportato entro un certo
range binario.
Come dicevamo in una vecchia discussione, finita poi tra me e Maurizio,
riguardante la sottrazione in virgola mobile, VBS non e' che "esula" da
questo problema.. Non e' che VBS utilizza una gestione diversa del
*calcolo*, quanto una gestione diversa della *visualizzazione* (li' se non
mi ricordo male, io e lui ci eravamo inizialmente fraintesi).
Infatti sia JS che VBS hanno memorizzato lo stesso valore (che a noi pare
"errato").
Non c'e' niente di anomalo, a prima occhiata, nelle casistiche che posti,
basta ristudiarsi un po' di matematica binaria applicata ai processori.
Io la feci ai tempi delle superiori e adesso ricordo decisamente quel poco
che mi serve tutti i giorni.. Un bel ripasso non mi farebbe male neanche a
me.
Maurizio e' sicuramente piu' indicato al momento per risponderti nel
dettaglio in queste casistiche, credo.. Io di riprendere in mano libri non
ho voglia ^_^"
... Ricordo ancora quando passai ai processori a 32bit, che potevi assegnare
numeri di una certa levatura.. su 286 davano errori di "overlflow".. ah, bei
tempi :°
(e' un periodo che mi sento nostalgico..)
--------------------------------
Inviato via 
http://usenet.libero.it

 ho voglia ^_^"
In questo periodo men che meno, infatti speravo di avere da voi un qualche
riferimento veloce sulla rete.

 eravamo inizialmente fraintesi).
Mi succede spesso; leggo i messaggi alla velocità del suono ed è facile
saltare qualche parola o non apprezzarne subito il significato.
Maurizio.

 moltiplicazione per 2) == -545128448 (NEGATIVO)
Anche questo è spiegabile anche se, secondo me, assomiglia tanto ad un bug.
JS con questa sua caratteristica di fare lo shift anche dei float, deve
convertire il float in una serie di bit, e poi, dopo lo shift, riconvertire
il risultato in float, interpretando i bit in modo diverso. Il bit più
significativo del numero diventa, probabilmente, il bit di segno. Le altre
cifre non le so interpretare così al volo; dovrei avere qualche minuto di
tempo per studiarle bene. Però che questo shift possa dar luogo ad un numero
senza senso è quasi da aspettarsi.
Faccio un esempio facile: prendiamo il numero 10 che in binario è 1010 e
supponiamo di avere solo 5 bit a disposizione di cui il quinto rappresenta
il segno. Quindi il numero è 01010. Se faccio lo shift a sinistra, questo
diventa: 10100 e cioè il numero 4 con segno negativo, cioè -4. So bene che i
numeri negativi vengono interpretati in maniera leggermente diversa, ma era
solo per dare un'idea.
Il presunto bug è che JS dovrebbe evitare di fare queste operazioni
(segnalando qualcosa, un overflow o non so che altro) quando si prevede che
vengano fuori risultati di questo tipo.
Maurizio.