Из документов Java для nextInt()
:
Все 2 32 возможные значения типа int создаются с (приблизительно) равной вероятностью.
Один из подходов заключается в использовании следующего преобразования:
s = rng.nextInt() & Integer.MAX_VALUE; // zero out the sign bit
Причина, по которой необходимо нечто подобное (в отличие от использования абсолютного значения или отрицания), заключается в том, что Integer.MIN_VALUE
слишком велико по абсолютному значению, чтобы превратить его в положительное целое число. То есть из-за переполнения Math.abs(Integer.MIN_VALUE) == Integer.MIN_VALUE
и Integer.MIN_VALUE == -Integer.MIN_VALUE
. Приведенное выше преобразование сохраняет примерно равномерное свойство распределения: если вы написали цикл создания и проверки, который просто отбрасывал Integer.MIN_VALUE
и возвращал абсолютное значение всего остального, то положительные целые числа были бы в два раза вероятнее нуля. При отображении Integer.MIN_VALUE
в ноль это приводит к вероятности нуля в соответствии с положительными целыми числами.
Вот еще один подход, который на самом деле может быть чуть-чуть быстрее (хотя я не тестировал его):
int s = rng.next(Integer.SIZE - 1); // Integer.SIZE == 32
Это сгенерирует целое число с 31 случайным битом младшего разряда (и 0 как 32 nd бит, гарантируя неотрицательное значение). Однако (как указано в комментарии jjb), поскольку next(int)
является protected
методом Random
, вам придется создать подкласс Random
, чтобы раскрыть метод (или предоставить подходящий прокси для метода ):
public class MyRandom extends Random {
public MyRandom() {}
public MyRandom(int seed) { super(seed); }
public int nextNonNegative() {
return next(Integer.SIZE - 1);
}
}
Другой подход заключается в использовании ByteBuffer
, который оборачивает 4-байтовый массив. Затем вы можете сгенерировать случайные четыре байта (вызвав nextBytes(byte[])
), обнулить знаковый бит и затем прочитать значение как int
. Я не верю, что это дает какое-то преимущество перед вышеперечисленным, но я подумал, что просто добавлю это. По сути, это то же самое, что и мое первое решение (оно маскируется Integer.MAX_VALUE
).
В более ранней версии этого ответа я предложил использовать:
int s = rng.nextInt(Integer.MAX_VALUE);
Однако, согласно документам это будет генерировать целые числа в диапазоне от 0 (включительно) до Integer.MAX_VALUE
(исключая). Другими словами, он не будет генерировать значение Integer.MAX_VALUE
. Кроме того, оказывается, что next(int)
всегда будет быстрее, чем nextInt(int)
.