Генерация случайных чисел в C

При поиске Учебных руководств при генерации случайных чисел в C я нашел эту тему

Когда я пытаюсь использовать rand() функция без параметров, я всегда добираюсь 0. Когда я пытаюсь использовать rand() функция с параметрами, я всегда получаю значение 41. И каждый раз, когда я пытаюсь использовать arc4random() и random() функции, я получаю ошибку LNK2019.

Вот то, что я сделал:

#include 
int main()
{
  int x;
  x = rand(6);
  printf("%d", x);
}

Этот код всегда генерирует 41. Где я иду не так, как надо? Я выполняю Windows XP SP3 и использую Командную строку VS2010 в качестве компилятора.

12
задан Community 23 May 2017 в 12:26
поделиться

5 ответов

Вы должны вызвать srand() перед вызовом rand для инициализации генератора случайных чисел.

Либо вызывайте его с определенным seed, и вы всегда будете получать одну и ту же псевдослучайную последовательность

#include <stdlib.h>

int main ()
{
  srand ( 123 );
  int random_number = rand();
  return 0;
}

либо вызывайте его с изменяющимися источниками, т.е. функцией времени

#include <stdlib.h>
#include <time.h>

int main ()
{
  srand ( time(NULL) );
  int random_number = rand();
  return 0;
}

В ответ на комментарий Moon rand() генерирует случайное число с равной вероятностью между 0 и RAND_MAX (макрос, предопределенный в stdlib.h)

Затем вы можете сопоставить это значение меньшему диапазону, например,

int random_value = rand(); //between 0 and RAND_MAX

//you can mod the result
int N = 33;
int rand_capped = random_value % N;  //between 0 and 32
int S = 50;
int rand_range = rand_capped + S; //between 50 and 82

//you can convert it to a float
float unit_random = random_value / (float) RAND_MAX; //between 0 and 1 (floating point)

Этого может быть достаточно для большинства случаев, но стоит отметить, что в первом случае использование оператора mod вносит небольшое смещение, если N не делится равномерно на RAND_MAX+1.

Генераторы случайных чисел интересны и сложны, широко распространено мнение, что генератор rand() в стандартной библиотеке C не является генератором случайных чисел высокого качества, читайте (http://en.wikipedia.org/wiki/Random_number_generation для определения качества).

http://en.wikipedia.org/wiki/Mersenne_twister (источник http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html ) - популярный высококачественный генератор случайных чисел.

Кроме того, я не знаю ни arc4rand(), ни random(), поэтому не могу прокомментировать.

31
ответ дан 2 December 2019 в 03:22
поделиться

Сначала вам нужно заполнить генератор, потому что он не генерирует реальных случайных чисел!

Попробуйте следующее:

#include <stdlib.h>
#include <time.h>
int main()
{
    // random seed, time!
    srand( time(NULL) ); // hackish but gets the job done.
    int x;
    x = rand(); // everytime it is different because the seed is different.
    printf("%d", x);
}
1
ответ дан 2 December 2019 в 03:22
поделиться

Вам нужно засеять свой ГПСЧ, чтобы он каждый раз начинал с другого значения.

Простой, но низкокачественный вариант - использовать текущее время:

srand(time(0));

Это поможет вам начать, но считается низкокачественным (т.е., например, не используйте это, если вы пытаетесь генерировать ключи RSA).

Предыстория. Генераторы псевдослучайных чисел не создают истинные последовательности случайных чисел, а лишь имитируют их. Если задать начальное число, ГПСЧ всегда будет выдавать одну и ту же последовательность чисел. По умолчанию они начинаются с одного и того же внутреннего состояния, поэтому возвращают одну и ту же последовательность.

Чтобы не получить ту же последовательность, вы изменяете внутреннее состояние. Акт изменения внутреннего состояния называется "посевом".

5
ответ дан 2 December 2019 в 03:22
поделиться

Кроме того, линейные конгруэнтные ГПСЧ имеют тенденцию создавать больше случайности в старших битах, чем в младших битах, поэтому для ограничения результата не используйте модуль по модулю, а вместо этого используйте что-то вроде:

j = 1 + (int) (10.0 * (rand() / (RAND_MAX + 1.0)));

(Это из «Числовых Рецепты в C », гл.7)

3
ответ дан 2 December 2019 в 03:22
поделиться
#include <stdlib.h>

int main()
{
    int x;
    x = rand(6);
    printf("%d", x);
}

Если вы новичок, вам следует попросить свой компилятор печатать каждое предупреждение о плохом коде, которое он может сгенерировать. Современные компиляторы знают множество различных предупреждений, которые помогут вам лучше программировать. Например, когда вы компилируете эту программу с помощью компилятора GNU C:

$ gcc -W -Wall rand.c
rand.c: In function `main':
rand.c:5: error: too many arguments to function `rand'
rand.c:6: warning: implicit declaration of function `printf'

Здесь вы получаете два предупреждения. Первый говорит, что функция rand принимает только ноль аргументов, а не один, как вы пытались. Чтобы получить случайное число от 0 до n , вы можете использовать выражение rand ()% n , что не идеально, но подходит для малых n .Результирующие случайные числа обычно распределяются неравномерно; меньшие значения возвращаются чаще.

Второе предупреждение сообщает вам, что вы вызываете функцию, о которой компилятор не знает на данный момент. Вы должны сообщить компилятору, сказав #include . Какие включаемые файлы необходимы, для каких функций не всегда просто, но запрос спецификации Open Group для переносимых операционных систем во многих случаях работает: http://www.google.com/search?q=opengroup+rand .

Эти два предупреждения многое расскажут об истории языка программирования C. 40 лет назад определение функции не включало количество параметров или типы параметров. Также можно было вызвать неизвестную функцию, которая в большинстве случаев работала. Если вы хотите написать код сегодня, вам не следует полагаться на эти старые функции, а вместо этого включить предупреждения компилятора, понять предупреждения и затем исправить их должным образом.

3
ответ дан 2 December 2019 в 03:22
поделиться
Другие вопросы по тегам:

Похожие вопросы: