Che funzioni non è affatto banale! È una proprietà della rappresentazione in virgola mobile IEEE che int∘floor = ⌊⋅⌋ se l'entità dei numeri in questione è abbastanza piccola, ma sono possibili diverse rappresentazioni dove int (floor (2.3)) potrebbe essere 1.
Questo post spiega perché funziona in quell'intervallo .
In un doppio, puoi rappresentare numeri interi a 32 bit senza problemi. Non ci possono essere problemi di arrotondamento. Più precisamente, i doppi possono rappresentare tutti i numeri interi compresi tra 2 53 e -2 53 compresi .
Breve spiegazione : un doppio può memorizzare fino a 53 cifre binarie. Quando hai bisogno di più, il numero è riempito con zero sulla destra.
Ne consegue che 53 sono il numero più grande che può essere memorizzato senza imbottitura. Naturalmente, tutti i numeri (interi) che richiedono meno cifre possono essere memorizzati con precisione.
Aggiungendo uno a 111 (omesso) 111 (53 quelli) si ottengono 100 ... 000, (53 zero). Come sappiamo, possiamo memorizzare 53 cifre, il che rende il riempimento zero più a destra.
Ecco da dove proviene 2 53 .
Maggiori dettagli: dobbiamo considerare come funziona IEEE-754 in virgola mobile.
1 bit 11 / 8 52 / 23 # bits double/single precision
[ sign | exponent | mantissa ]
Il numero viene quindi calcolato come segue (esclusi casi speciali che qui non sono rilevanti):
-1 segno × 1.mantissa × 2 esponente - bias
dove bias = 2 esponente - 1 - 1 , ovvero 1023 e 127 rispettivamente per doppia / singola precisione.
Sapendo che la moltiplicazione per 2 X sposta semplicemente tutti i bit X posti a sinistra, è facile vedere che qualsiasi numero intero deve avere tutti i bit nella mantissa che finiscono a destra del punto decimale su zero.
Qualsiasi numero intero tranne zero ha la seguente forma in binario:
1x ... x dove le x -es rappresentano i bit a destra dell'MSB (bit più significativo).
Poiché abbiamo escluso zero, ci sarà sempre un MSB che è uno, motivo per cui non è memorizzato. Per memorizzare il numero intero, dobbiamo portarlo nella forma sopra menzionata: -1 segno × 1.mantissa × 2 esponente - bias .
Ciò equivale a spostare i bit sopra il punto decimale fino a quando non c'è solo l'MSB verso la sinistra dell'MSB. Tutti i bit a destra del punto decimale vengono quindi memorizzati nella mantissa.
Da questo, possiamo vedere che possiamo memorizzare al massimo 52 cifre binarie oltre al MSB.
Ne consegue che il numero più alto in cui tutti i bit sono memorizzati in modo esplicito è
111(omitted)111. that's 53 ones (52 + implicit 1) in the case of doubles.
Per questo, dobbiamo impostare l'esponente, in modo che il punto decimale venga spostato di 52 posizioni. Se dovessimo aumentare l'esponente di uno, non possiamo conoscere la cifra a destra dopo il punto decimale.
111(omitted)111x.
Per convenzione, è 0. Impostando l'intera mantissa su zero, riceviamo il seguente numero:
100(omitted)00x. = 100(omitted)000.
Questo è un 1 seguito da 53 zero, 52 memorizzati e 1 aggiunto a causa dell'esponente.
Rappresenta 2 53 , che segna il confine (sia negativo che positivo) tra cui possiamo rappresentare accuratamente tutti i numeri interi. Se volessimo aggiungere uno a 2 53 , dovremmo impostare lo zero implicito (indicato da x
) su uno, ma è impossibile.
math.floor
restituisce un float in v2.6 , ma restituisce un numero intero in v3 . A questo punto (quasi sei anni dopo il PO), questo problema potrebbe presentarsi raramente.