Questo risultato non mi sorprende dato come vengono rappresentati i numeri in virgola mobile. Supponiamo di avere un tipo a virgola mobile molto breve con solo 4 bit di precisione. Se dovessimo generare un numero casuale compreso tra 0 e 1, distribuita in modo uniforme, ci sarebbero 16 possibili valori:
0.0000
0.0001
0.0010
0.0011
0.0100
...
0.1110
0.1111
Se questo è il modo in cui guardavano nella macchina, si potrebbe verificare il bit a basso fine di ottenere un Distribuzione 50/50. Tuttavia, i galleggianti IEEE sono rappresentati come una potenza di 2 volte una mantissa; un campo nel float è la potenza di 2 (più un offset fisso). La potenza di 2 è selezionata in modo che la parte "mantissa" sia sempre un numero> = 1.0 e < 2.0. Ciò significa che, in effetti, i numeri diversi 0.0000
sarebbero rappresentati simili:
0.0001 = 2^(-4) x 1.000
0.0010 = 2^(-3) x 1.000
0.0011 = 2^(-3) x 1.100
0.0100 = 2^(-2) x 1.000
...
0.0111 = 2^(-2) x 1.110
0.1000 = 2^(-1) x 1.000
0.1001 = 2^(-1) x 1.001
...
0.1110 = 2^(-1) x 1.110
0.1111 = 2^(-1) x 1.111
(Il 1
prima del punto binario è un valore implicito; per galleggianti 32 e 64 bit, nessun bit è in realtà assegnato per contenere questo 1
.)
Ma guardando a quanto sopra dovrebbe dimostrare perché, se si converte la rappresentazione in bit e si guarda il bit basso, si otterrà zero il 75% delle volte. Ciò è dovuto a tutti i valori inferiori a 0,5 (binario 0.1000
), che è la metà dei valori possibili, avendo spostato la loro mantissa, causando la comparsa di 0 nel bit basso. La situazione è essenzialmente la stessa quando la mantissa ha 52 bit (escluso l'implicito 1) come fa double
.
(In realtà, come @sneftel suggerito in un commento, abbiamo potuto includere più di 16 possibili valori nella distribuzione, generando:
0.0001000 with probability 1/128
0.0001001 with probability 1/128
...
0.0001111 with probability 1/128
0.001000 with probability 1/64
0.001001 with probability 1/64
...
0.01111 with probability 1/32
0.1000 with probability 1/16
0.1001 with probability 1/16
...
0.1110 with probability 1/16
0.1111 with probability 1/16
Ma io non sono sicuro che sia il tipo di distribuzione la maggior parte dei programmatori si aspetterebbe, quindi probabilmente non ne vale la pena, in più non guadagna molto quando i valori vengono utilizzati per generare numeri interi, come spesso accade con valori a virgola mobile casuali.)
Spero davvero che la risposta sia qualcosa di affascinante sulla generazione casuale di variabili a virgola mobile, piuttosto che "LCG ha bassa entropia nei bit bassi". – Sneftel
Sono molto curioso, qual è lo scopo di un "hash 1 bit per doppio"? Non posso seriamente pensare a nessuna applicazione legittima di un simile requisito. – corsiKa
@corsiKa Nei calcoli geometrici ci sono spesso due casi che stiamo cercando di scegliere tra due possibili risposte (ad es. È un punto a sinistra oa destra della linea?), Ea volte introduce il terzo caso degenerato (punto è giusto sulla linea), ma hai solo due risposte disponibili, quindi devi scegliere in modo pseudocasuale una delle risposte disponibili in quel caso. Il modo migliore che posso pensare è di prendere un hash 1 bit di uno dei doppi valori dati (ricordate, quelli sono calcoli geometrici, quindi ci sono i doppi dappertutto). – gvlasov