Desde el Java docs for nextInt()
:
Todos 2 posibles valores int se producen con (aproximadamente) igual probabilidad.
Un método consiste en utilizar el siguiente transformar:
s = rng.nextInt() & Integer.MAX_VALUE; // zero out the sign bit
La razón algo como esto que se necesita (en lugar de utilizar el valor absoluto o negación) es que Integer.MIN_VALUE
es demasiado grande en valor absoluto para ser convertido en un entero positivo. Es decir, debido al desbordamiento, Math.abs(Integer.MIN_VALUE) == Integer.MIN_VALUE
y Integer.MIN_VALUE == -Integer.MIN_VALUE
. La transformación anterior conserva la propiedad de distribución aproximadamente uniforme: si escribió un ciclo de generar y probar que simplemente arrojó Integer.MIN_VALUE
y devolvió el valor absoluto de todo lo demás, entonces los enteros positivos tendrían el doble de probabilidad que cero. Al asignar Integer.MIN_VALUE
a cero, eso hace que la probabilidad de cero esté en línea con los enteros positivos.
Aquí es otro enfoque, que puede ser en realidad un poquito más rápido (aunque no he referenciado IT):
int s = rng.next(Integer.SIZE - 1); // Integer.SIZE == 32
Esto generará un número entero con 31 bits de orden al azar (y 0 como el 32 nd bit, garantizando un valor no negativo). Sin embargo (como se señala en el comentario de jjb), ya que es un método next(int)
protected
de Random
, que tendrá que subclase Random
para exponer el método (o para proporcionar un sustituto adecuado para el método):
public class MyRandom extends Random {
public MyRandom() {}
public MyRandom(int seed) { super(seed); }
public int nextNonNegative() {
return next(Integer.SIZE - 1);
}
}
Otro enfoque es usar un ByteBuffer
que envuelve una matriz de 4 bytes. A continuación, puede generar cuatro bytes aleatorios (llamando al nextBytes(byte[])
), poner a cero el bit de signo y luego leer el valor como int
. No creo que esto ofrezca ninguna ventaja sobre lo anterior, pero pensé que simplemente lo lanzaría allí. Es básicamente lo mismo que mi primera solución (que enmascara con Integer.MAX_VALUE
).
En una versión anterior de esta respuesta, me sugirió usando:
int s = rng.nextInt(Integer.MAX_VALUE);
Sin embargo, de acuerdo con the docs Esto generará números enteros en el rango de 0 (incluido) a Integer.MAX_VALUE
(exclusivo). En otras palabras, no generará el valor Integer.MAX_VALUE
. Además, resulta que next(int)
siempre será más rápido que nextInt(int)
.
solo cree lo que lee en los javadocs. Y (por supuesto) ** lea los javadocs **. –
Nota 'Math.abs' no funcionará una sola vez en 2 . (Y buena suerte probar eso. Sugerencia: No use un objeto mutable estático.) –