Edycja: Więc w zasadzie to, co próbuję napisać, to 1-bitowy hash double.
Chcę zmapować doubledo truelub falsez 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, yjeśli wynosi 1, lub njeśli jest 0.
Jednak ten kod stale daje 25% yi 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 doublejest tym, co dzieje się, gdy postępujesz zgodnie z tym podejściem do końca, z najmniejszym możliwym modulo.
(lastbit & 3) == 0zadziała, choć to dziwne.
