Editar: Entonces, básicamente, lo que estoy tratando de escribir es un hash de 1 bit double
.
Quiero mapear un double
to true
o false
con una probabilidad de 50/50. Para eso escribí un código que selecciona algunos números aleatorios (solo como ejemplo, quiero usar esto en datos con regularidades y aún así obtener un resultado 50/50) , verifica su último bit e incrementos y
si es 1, o n
si es 0.
Sin embargo, este código constantemente produce 25% y
y 75% n
. ¿Por qué no es 50/50? ¿Y por qué una distribución tan extraña pero directa (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);
}
}
Salida de ejemplo:
250167 749833
doubleValue % 1 > 0.5
, pero eso sería demasiado grano ya que puede introducir regularidades visibles en algunos casos (todos los valores están dentro del rango de longitud 1). Si eso es demasiado de grano grueso, ¿deberíamos intentar rangos más pequeños, como doubleValue % 1e-10 > 0.5e-10
? Bueno, sí. Y tomar solo el último bit como hash de a double
es lo que sucede cuando sigues este enfoque hasta el final, con el mínimo módulo posible.
(lastbit & 3) == 0
funcionaría sin embargo, por extraño que sea.