Modifica: Quindi sostanzialmente quello che sto cercando di scrivere è un hash a 1 bit per double
.
Voglio mappare un double
a true
o false
con una probabilità 50/50. Per questo ho scritto un codice che seleziona alcuni numeri casuali (solo come esempio, voglio usarlo su dati con regolarità e ottenere comunque un risultato 50/50) , controlla il loro ultimo bit e incrementa y
se è 1, o n
se lo è 0.
Tuttavia, questo codice risulta costantemente nel 25% y
e nel 75% n
. Perché non è 50/50? E perché una distribuzione così strana, ma diretta (1/3)?
public class DoubleToBoolean {
@Test
public void test() {
int y = 0;
int n = 0;
Random r = new Random();
for (int i = 0; i < 1000000; i++) {
double randomValue = r.nextDouble();
long lastBit = Double.doubleToLongBits(randomValue) & 1;
if (lastBit == 1) {
y++;
} else {
n++;
}
}
System.out.println(y + " " + n);
}
}
Esempio di output:
250167 749833
doubleValue % 1 > 0.5
, ma sarebbe troppo grossolano poiché in alcuni casi può introdurre regolarità visibili (tutti i valori sono compresi nell'intervallo di lunghezza 1). Se è troppo a grana grossa, allora dovremmo probabilmente provare intervalli più piccoli, come doubleValue % 1e-10 > 0.5e-10
? Beh si. E prendere solo l'ultimo bit come hash di a double
è ciò che accade quando segui questo approccio fino alla fine, con il modulo il meno possibile.
(lastbit & 3) == 0
funzionerebbe comunque, per quanto sia strano.