Java Random дает отрицательные числа - PullRequest
32 голосов
/ 29 апреля 2011

У меня проблемы с классом Javas Random, если я сделаю это:

Random rng = new Random(seed) // seed == 29 in this example

String ss = "";
        for(int i = 0; i < 10; i++)
        {
            int s = rng.nextInt();
            ss += Integer.toString(s);
            ss +="\n";
        }

Вот что я получу обратно:

-1169335537
-2076183625
1478047223
1914482305
722089687
2094672350
-1234724057
-1614953544
-321574001
1000360613

Из того, что я прочиталэто должно только возвращать положительные числа для начала?

Это может быть немного надуманным, но это не может иметь ничего общего с запуском 64-битной машины в 64-битной Windows 7?

Любойпомощь вообще была бы огромной потребностью, чтобы закончить это для руки назначения сегодня!

Ответы [ 8 ]

59 голосов
/ 29 апреля 2011

Из документов 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).

13 голосов
/ 27 апреля 2016

Поскольку существует равный шанс положительных или отрицательных чисел, почему бы не просто:

Math.abs(rand.nextInt())

Красиво и просто!

8 голосов
/ 29 апреля 2011

Допускаются отрицательные числа - возможно, вы читали о подобном методе Random nextInt (int) , который делает ограничивает возвращаемые значения нулем или больше.

1 голос
/ 29 апреля 2011

Ознакомьтесь с документацией для java.util.Random:

http://download.oracle.com/javase/6/docs/api/java/util/Random.html

Вы пытаетесь получить случайные числа от 0 до 28?Если это так, вам нужно использовать nextInt (int), как упоминалось ранее.Семя не имеет отношения к диапазону возможных результатов или их относительной вероятности.

0 голосов
/ 19 марта 2017

Если вам довелось работать с числами, которые могут иметь отрицательное значение, вы можете автоматически превратить его в положительное значение, используя условное объявление, умножив значение на отрицательное.Вы можете также превратить положительное в отрицательное значение, используя тот же метод.

Примеры приведены ниже.

// Turn a negative value into its positive correspondent value.
// If the value is already a positive value, nothing will happen to it.
int a = -5;
a = a < 0? a * -1 : a;

// Turn a positive value into its negative correspondent value.
// If the value is already a negative value, nothing will happen to it.
int b = 5;
b = b > 0? b * -1 : b;
0 голосов
/ 29 июля 2014
int s = rng.nextInt(seed); //seed 29 in this case

Это будет иметь предел от 0 до 29 .

0 голосов
/ 29 апреля 2011

Вы также можете использовать Math.random () , который возвращает значения от 0 до 1

0 голосов
/ 29 апреля 2011

Согласно документации http://download.oracle.com/javase/6/docs/api/java/util/Random.html#nextInt():

Возвращает следующее псевдослучайное, равномерно распределенное значение int из последовательности этого генератора случайных чисел.Общий контракт nextInt заключается в том, что одно значение int генерируется и возвращается псевдослучайно.Все 2 ^ 32 возможных значений int создаются с (приблизительно) равной вероятностью.

Просто умножьте на -1, если значение отрицательное

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...