I numeri in JavaScript sono IEEE-754 in virgola mobile a doppia precisione, un formato abbastanza compatto (64 bit) che fornisce calcoli veloci e una vasta gamma. Lo fa memorizzando il numero come un segno bit, un esponente di 11 bit e un significando a 52 bit (sebbene attraverso l'intelligenza in realtà ottiene 53 bit di precisione). È binario (base 2) in virgola mobile: il significando (più un po 'di intelligenza) ci dà il valore e l'esponente ci dà la grandezza del numero.
Naturalmente, con così tanti bit significativi, non tutti i numeri possono essere memorizzati. Qui è il numero 1, e il successivo numero più alto dopo 1 che il formato in grado di memorizzare, 1 + 2 -52 ≈ 1,00000000000000022, e il successivo più alto, dopo che 1 + 2 × 2 -52 ≈ 1,00000000000000044:
+ ------------------------------------------------- -------------- segno bit
/ + ------- + ---------------------------------------- -------------- esponente
/ / | + ------------------------------------------------- + - significand
/ / | / |
0 01111111111 00000000000000000000000000000000000000000000000000
= 1
0 01111111111 00000000000000000000000000000000000000000000000001
≈ 1.00000000000000022
0 01111111111 0000000000000000000000000000000000000000000000000010
≈ 1.00000000000000044
Notare il salto da 1.00000000000000022 a 1.00000000000000044; non c'è modo di memorizzare 1.0000000000000003. Ciò può accadere anche con i numeri interi: Number.MAX_SAFE_INTEGER(9,007,199,254,740,991) è il valore intero positivo più alto che il formato può contenere ie i + 1sono entrambi esattamente rappresentabili ( spec ). Possono essere rappresentati sia 9.007.199.254.740.991 che 9.007.199.254.740.992, ma il numero intero successivo , 9.007.199.254.740.993, non può; il numero intero successivo che possiamo rappresentare dopo 9.007.199.254.740.992 è 9.007.199.254.740.994. Di seguito sono riportati i modelli di bit, nota il bit più a destra (meno significativo):
+ ------------------------------------------------- -------------- segno bit
/ + ------- + ---------------------------------------- -------------- esponente
/ / | + ------------------------------------------------- + - significand
/ / | / |
0 10000110011 1111111111111111111111111111111111111111111111111111
= 9007199254740991 (Number.MAX_SAFE_INTEGER)
0 10000110100 00000000000000000000000000000000000000000000000000
= 9007199254740992 (Number.MAX_SAFE_INTEGER + 1)
x xxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
9007199254740993 (Number.MAX_SAFE_INTEGER + 2) non può essere memorizzato
0 10000110100 0000000000000000000000000000000000000000000000000001
= 9007199254740994 (Number.MAX_SAFE_INTEGER + 3)
Ricorda, il formato è in base 2 e con quell'esponente il bit meno significativo non è più frazionario; ha un valore di 2. Può essere disattivato (9.007.199.254.740.992) o attivo (9.007.199.254.740.994); quindi a questo punto, abbiamo iniziato a perdere precisione anche sulla scala dei numeri interi (interi). Che ha implicazioni per il nostro ciclo!
Dopo aver completato il i = 9,007,199,254,740,992ciclo, i++ci dà ... di i = 9,007,199,254,740,992nuovo; non ci sono cambiamenti i, perché il numero intero successivo non può essere memorizzato e il calcolo finisce per arrotondare per difetto. icambierebbe se lo facessimo i += 2, ma i++non possiamo cambiarlo. Quindi abbiamo raggiunto lo stato stazionario: inon cambia mai e il ciclo non termina mai.