Почему С++ rand(), кажется, генерирует только числа того же порядка величины?

В небольшом приложении, написанном на C/С++, я столкнулся с проблемой с функцией rand и, возможно, с семенем:

Я хочу создать последовательность случайных чисел, которые имеют разные порядки, т.е. с разными значениями логарифма (база 2). Но, кажется, все произведенные числа имеют один и тот же порядок, колеблющийся только между 2 ^ 25 и 2 ^ 30.

Это потому, что rand() засевается временем Unix, которое к настоящему времени является относительно большим числом? Что я забываю? Я посеял rand() только один раз в начале main().

Ответ 1

Есть только 3% чисел между 1 и 2 30 которые НЕ находятся между 2 25 и 2 30. Итак, это звучит довольно нормально:)

Поскольку 2 25/2 30= 2 -5= 1/32 = 0,03125 = 3,125%

Ответ 2

Более светлый зеленый - это область между 0 и 2 25; темная зеленая - это область между 2 25 и 2 30. Тики имеют степень 2.

distribution

Ответ 3

Вы должны быть более точными: вам нужны разные значения логарифма базы 2, но какой дистрибутив вы хотите для этого? Стандартные функции rand() генерируют равномерное распределение, вам нужно будет преобразовать этот результат, используя функцию квантиля, связанную с распределением, которое вы хотите.

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

Ответ 4

Если вы хотите разные порядки, почему бы просто не попробовать pow(2, rand())? Или, может быть, выбрать порядок непосредственно как rand(), как предложил Гарольд?

Ответ 5

@C4stor сделал отличный момент. Но для более общего случая и более простого для понимания человека (основа 10): для диапазона от 1 до 10 ^ n ~ 90% чисел от 10 ^ (п-1) до 10 ^ п, следовательно, ~ 99% чисел идут от 10 ^ (п-2) до 10 ^ п. Продолжайте добавлять столько десятичных дробей, сколько хотите.

Смешная математика, если вы продолжаете делать это для n, вы можете видеть, что от 1 до 10 ^ n, 99.9999...% = 100% от этого метода от 10 ^ 0 до 10 ^ п.

Теперь о коде, если вы хотите случайное число со случайными порядками, от 0 до 10 ^ n, вы можете сделать:

  • Создайте небольшое случайное число от 0 до n

  • Если вам известен диапазон, который имеет n, сгенерируйте большое случайное число порядка 10 ^ k, где k > max {n}.

  • Сократите более длинное случайное число, чтобы получить n цифр этого большого случайного числа.

Ответ 6

Основной (и правильный) ответ уже был дан и принят выше: есть 10 чисел между 0 и 9, 90 номеров между 10 и 99, 900 между 100 и 999 и т.д.

Для расчетно-эффективного способа получения распределения с приблизительно логарифмическим распределением вы хотите изменить случайное число на случайное число:

s = rand() & 31; // a random number between 0 and 31 inclusive, assuming RAND_MAX = 2^32-1
r = rand() >> s; // right shift

Это не идеально, но намного быстрее, чем вычисление pow(2, rand()*scalefactor). Он будет "комковатым" в том смысле, что распределение будет равномерным для чисел в коэффициенте 2 (равномерное для 128-255, половина плотности для 256 до 1023 и т.д.).

Вот гистограмма частоты чисел от 0 до 31 (в 1М выборках):

enter image description here

Ответ 7

Существует ровно равное количество чисел между 0 и 2 ^ 29 и 2 ^ 29 и 2 ^ 30.

Другой способ взглянуть на проблему: рассмотреть двоичное представление произвольного числа, которое вы генерируете, вероятность того, что старший бит равен 1, равно 1/2, и, следовательно, вы получите порядок 29 в половине случаев. Вы хотите увидеть число, которое будет ниже 2 ^ 25, но это означает, что 5 старших бит равны нулю, что происходит с низкой вероятностью 1/32. Скорее всего, даже если вы запустите его в течение долгого времени, вы никогда не увидите порядка ниже 15 (вероятность - это что-то вроде прокатки 6 6 раз подряд).

Теперь, часть вашего вопроса о семени. Нет, семя не может определить диапазон, из которого генерируются числа, он просто определяет первый, начальный элемент. Подумайте о rand() как о последовательности всех возможных чисел в диапазоне (предопределенная перестановка). Семя определяет, где вы начинаете рисовать числа из последовательности. Вот почему, если вы хотите (псевдо) случайности, вы используете текущее время для инициализации последовательности: вам все равно, что позиция, с которой вы начинаете, неравномерно распределена, все, что имеет значение, состоит в том, что вы никогда не начинаете с той же позиции.

Ответ 8

использование pow(2,rand()) он даст ответы в порядке желаемой величины!!

Ответ 9

Если вы хотите использовать случайные числа из онлайн-сервиса, вы можете использовать wget для этого, вы можете захотеть увидеть вы также можете использовать такие услуги, как random.org для генерации случайных чисел, вы можете поймать их с помощью wget, а затем прочитать числа из загруженного файла.

wget -q https://www.random.org/integers/?num=100&min=1&max=100&col=5&base=10&format=html&rnd=new -O new.txt

http://programmingconsole.blogspot.in/2013/11/a-better-and-different-way-to-generate.html