sei traboccante la capacità di JavaScript tipo di numero, vedere §8.5 of the spec per i dettagli. Questi ID dovranno essere stringhe.
IEEE-754 virgola mobile a precisione doppia (il tipo di numero utilizzato da JavaScript) non può rappresentare precisamente tutti i numeri (ovviamente). Notoriamente, 0.1 + 0.2 == 0.3
è falso. Questo può influenzare numeri interi proprio come influenza numeri frazionari; inizia una volta superato 9,007,199,254,740,991 (Number.MAX_SAFE_INTEGER
).
Oltre Number.MAX_SAFE_INTEGER + 1
(9007199254740992
), il formato a virgola mobile IEEE-754 non può più rappresentare ogni intero consecutivo. 9007199254740991 + 1
è 9007199254740992
, ma 9007199254740992 + 1
è anche9007199254740992
perché 9007199254740993
non può essere rappresentato nel formato. Il prossimo che può essere è 9007199254740994
. Quindi non può essere 9007199254740995
, ma 9007199254740996
can.
Il motivo è che abbiamo esaurito i bit, quindi non abbiamo più un bit da 1s; il bit di ordine inferiore ora rappresenta multipli di 2. Alla fine, se continuiamo, perdiamo quel bit e funzionano solo in multipli di 4. E così via.
I valori sono pozzetto superiori a tale soglia e pertanto vengono arrotondati al valore rappresentativo più vicino.
Se siete curiosi di sapere i bit, ecco cosa succede: un binario numero a virgola mobile a doppia precisione IEEE-754 ha un bit di segno, 11 bit di esponente (che definisce la dimensione complessiva del numero , come potenza di 2 [perché questo è un formato binario]), e 52 bit di significato e (ma il formato è così intelligente ottiene 53 bit di precisione da quei 52 bit). Il modo in cui viene utilizzato l'esponente è complicato (described here), ma in molto termini vaghi, se ne aggiungiamo uno all'esponente, il valore del significato è raddoppiato, poiché l'esponente è usato per le potenze di 2 (di nuovo, avvertenza, non è diretto, c'è intelligenza lì dentro).
Quindi diamo un'occhiata al valore 9007199254740991
(aka, Number.MAX_SAFE_INTEGER
):
+−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−− sign bit
/ +−−−−−−−+−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−− exponent
// | +−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−+− significand
// |/ |
0 10000110011 1111111111111111111111111111111111111111111111111111
= 9007199254740991 (Number.MAX_SAFE_INTEGER)
Tale valore esponente, 10000110011
, significa che ogni volta che aggiungiamo una al significante, il numero rappresentato sale di 1 (il intero numero 1, abbiamo perso la capacità di rappresentare numeri frazionari molto prima).
Ma ora questo significato è pieno. Per superare quel numero, dobbiamo aumentare l'esponente, il che significa che se ne aggiungiamo uno al significando, il valore del numero rappresentato sale di 2, non di 1 (perché l'esponente è applicato a 2, la base di questo numero binario in virgola mobile):
+−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−− sign bit
/ +−−−−−−−+−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−− exponent
// | +−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−+− significand
// |/ |
0 10000110100 0000000000000000000000000000000000000000000000000000
= 9007199254740992 (Number.MAX_SAFE_INTEGER + 1)
Beh, va bene, perché è 9007199254740991 + 1
9007199254740992
comunque. Ma! Non possiamo rappresentare 9007199254740993
. Abbiamo finito i bit. Se aggiungiamo solo 1 per il significante, si aggiunge 2 al valore:
+−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−− sign bit
/ +−−−−−−−+−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−− exponent
// | +−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−+− significand
// |/ |
0 10000110100 0000000000000000000000000000000000000000000000000001
= 9007199254740994 (Number.MAX_SAFE_INTEGER + 3)
Il formato solo non può rappresentare più numeri dispari, come si aumenta il valore, l'esponente è troppo grande.
Alla fine, esauriamo nuovamente significato e bit e dobbiamo aumentare l'esponente, quindi finiamo per essere in grado di rappresentare solo multipli di 4. Quindi multipli di 8. Quindi multipli di 16. E così via.
Grazie a tutti per le risposte rapide e utili, vorrei poter contrassegnare tutte e 3 le risposte ufficiali. – Jaanus