Как использовать функцию rand для создания чисел в определенном диапазоне? - PullRequest
5 голосов
/ 24 ноября 2010

Я хотел бы сделать случайные числа в определенном диапазоне, например «выбрать случайное число от 18 до 35»?Как я могу сделать это с помощью функции rand()?

Ответы [ 4 ]

12 голосов
/ 24 ноября 2010

В зависимости от языка, который вы используете, встроенный генератор случайных чисел может уже есть такая возможность - сделайте немного больше исследований.

Предположим, что генератор случайных чисел, который у вас есть, всегда возвращает числа в некотором заданном диапазоне. Просто ради аргумента, допустим, диапазон составляет 0,65536, но вам нужны случайные числа в диапазоне Low..High, 18..35 в вашем примере.

Неправильный способ сделать это будет что-то вроде:

 r = (rand() % (High - Low + 1)) + Low

rand () возвращает число в диапазоне 0..65536. Возьмите остаток после деления на (Высокий - Низкий + 1), который в этом примере (35-18 + 1 = 18). Результатом является число между 0..17. К этому вы добавляете Low (18), который сдвигает результат, r, в диапазон 18..35. Диапазон Вы ищете.

Числа, сгенерированные таким образом, не имеют равномерного распределения в тех случаях, когда используется делитель чтобы получить остаток не является четным кратным верхнего предела, возвращаемого функция rand (). См. Алгоритм Фишера-Йетса - Смещение по модулю . Чтобы устранить это смещение, вам нужно вычислить наибольшее число, которое меньше того, которое возвращает rand (), но равномерно делит на (High - Low + 1). В вашем случае это 3640 * 18 = 65520. Используйте это как фильтр высоких частот на числах возвращается через rand () как следующим образом:

  do forever {
     r = rand()
     if r <= 65520 then {
         r = (r % (High - Low + 1)) + Low
         break
         }
     } 

Теперь генерируемые вами случайные числа должны иметь те же характеристики распределения, что и rand ().

6 голосов
/ 24 ноября 2010

Если это написано на C, то вы довольно близки. Компилируем этот код:

#include <stdio.h>
#include <stdlib.h>

int main() {
    int i;
    for (i = 0; i < 1000000; i++) {
        printf("%d\n", rand()%(35-18+1)+18);
    }
}

И запуск его в конвейере приводит к выводу:

chris@zack:~$ gcc -o test test.c
chris@zack:~$ ./test | sort | uniq -c
  55470 18
  55334 19
  55663 20
  55463 21
  55818 22
  55564 23
  55322 24
  55886 25
  55947 26
  55554 27
  55342 28
  55526 29
  55719 30
  55435 31
  55669 32
  55818 33
  55205 34
  55265 35

Ключ, который вы забыли добавить 1 - ошибка забора .

Вы можете обобщить это в функцию:

int random_between(int min, int max) {
    return rand() % (max - min + 1) + min;
}
0 голосов
/ 24 ноября 2010
  1. Вы хотите только целые числа?
  2. Хотите равномерное распределение?
  3. Хотите ли вы включить 18 и 35 в качестве возможных значений?
  4. Какой язык вы бы предпочли использовать?

в общем случае, если rand () возвращает значение с плавающей запятой в [0.0 ... 1.0) (то есть вы можете получить значения, произвольно близкие к 1,0, но не на самом деле 1) тогда вам захочется что-то вроде

hi = 36
lo = 18
res = int( (hi-lo)*rand() + lo ) # returns random values in 18..35

Обратите внимание, что это никогда не вернет значение hi - поэтому я имею увеличьте его на 1 (т.е. вы получите все значения от 18 до 35 включительно, но не 36).

Надеюсь, это поможет.

0 голосов
/ 24 ноября 2010

предположим, что rand () даст вам число от 0 до 1.0

, затем используйте rand () * (35 - 18) + 18, чтобы получить случайное число от 18 до 35.

Изменить: вам не нужен мод для этого.

...