Edycja: Więc w zasadzie to, co próbuję napisać, to 1-bitowy hash double
.
Chcę zmapować double
do true
lub false
z szansą 50/50. W tym celu napisałem kod, który wybiera losowe liczby (tak jak na przykład, chcę tego użyć na danych z regularnościami i nadal otrzymuję wynik 50/50) , sprawdza ich ostatni bit i przyrosty, y
jeśli wynosi 1, lub n
jeśli jest 0.
Jednak ten kod stale daje 25% y
i 75% n
. Dlaczego nie jest to 50/50? A skąd taka dziwna, ale prosta (1/3) dystrybucja?
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);
}
}
Przykładowe dane wyjściowe:
250167 749833
doubleValue % 1 > 0.5
, ale byłoby to zbyt gruboziarniste, ponieważ w niektórych przypadkach może wprowadzić widoczne regularności (wszystkie wartości mieszczą się w zakresie długości 1). Jeśli jest zbyt gruboziarnisty, czy powinniśmy prawdopodobnie spróbować mniejszych zakresów, na przykład doubleValue % 1e-10 > 0.5e-10
? No tak. Przyjmowanie ostatniego kawałka jako skrótu double
jest tym, co dzieje się, gdy postępujesz zgodnie z tym podejściem do końca, z najmniejszym możliwym modulo.
(lastbit & 3) == 0
zadziała, choć to dziwne.