Как я могу получить исходный код для rand() (C++)?

Я новичок в программировании.

Я хочу точно знать, что делает rand().

Поиск только дает примеры его использования. Но никто не объясняет каждый шаг того, как функция генерирует случайное число. Они рассматривают rand() как черный ящик.

Я хочу знать, что делает rand(); каждый шаг.

Есть ли ресурс, который позволит мне точно узнать, что делает rand()? Это все с открытым исходным кодом, не так ли? Я согласен на разборку, если нет источника.

Я знаю, что он возвращает случайное число, но как он генерирует это число? Я хочу видеть каждый шаг.

Спасибо.

7 ответов

Решение

Это было 10 секунд поиска в Google:

...

Я собирался перечислить фактический поиск, но видя, что это явно дурак, я просто проголосую как дурак

Вот текущая реализация glibc:

/* Return a random integer between 0 and RAND_MAX.  */
int
rand (void)
{
  return (int) __random ();
}

Это не сильно помогает, но __random в конце концов звонит __random_r:

/* If we are using the trivial TYPE_0 R.N.G., just do the old linear
   congruential bit.  Otherwise, we do our fancy trinomial stuff, which is the
   same in all the other cases due to all the global variables that have been
   set up.  The basic operation is to add the number at the rear pointer into
   the one at the front pointer.  Then both pointers are advanced to the next
   location cyclically in the table.  The value returned is the sum generated,
   reduced to 31 bits by throwing away the "least random" low bit.
   Note: The code takes advantage of the fact that both the front and
   rear pointers can't wrap on the same call by not testing the rear
   pointer if the front one has wrapped.  Returns a 31-bit random number.  */

int
__random_r (buf, result)
     struct random_data *buf;
     int32_t *result;
{
  int32_t *state;

  if (buf == NULL || result == NULL)
    goto fail;

  state = buf->state;

  if (buf->rand_type == TYPE_0)
    {
      int32_t val = state[0];
      val = ((state[0] * 1103515245) + 12345) & 0x7fffffff;
      state[0] = val;
      *result = val;
    }
  else
    {
      int32_t *fptr = buf->fptr;
      int32_t *rptr = buf->rptr;
      int32_t *end_ptr = buf->end_ptr;
      int32_t val;

      val = *fptr += *rptr;
      /* Chucking least random bit.  */
      *result = (val >> 1) & 0x7fffffff;
      ++fptr;
      if (fptr >= end_ptr)
    {
      fptr = state;
      ++rptr;
    }
      else
    {
      ++rptr;
      if (rptr >= end_ptr)
        rptr = state;
    }
      buf->fptr = fptr;
      buf->rptr = rptr;
    }
  return 0;

 fail:
  __set_errno (EINVAL);
  return -1;
}

Вы можете просмотреть исходный код для различных реализаций стандарта C.

На вопрос, на который уже был дан ответ, вы можете найти то, что ищете. Какие распространенные алгоритмы используются для C rand()?

Этот ответ предоставляет код для реализации rand () в glibc

Я думаю, это то, что вы ищете. Он содержит подробное объяснение случайной функции и простую C-программу для понимания алгоритма.

Редактировать:

Вы должны проверить это также. Возможный дубликат.

Ну, я считаю, что rand из стандартной библиотеки C, а не из стандартной библиотеки C++. Нет ни одной реализации ни одной библиотеки, их несколько.

Вы можете пойти куда-нибудь на эту страницу, чтобы посмотреть исходный код для glibc, библиотеки c, используемой в большинстве дистрибутивов Linux. Для glibc вы найдете его в исходных файлах под stdlib, таких как rand.c а также random.c,

Другая реализация, такая как uClibc, может быть проще для чтения. Попробуйте здесь в папке libc/stdlib.

Простейшими достаточно хорошими генераторами псевдослучайных чисел являются линейные конгруэнтные генераторы (LCG). Это итерации формулы, такие как

X_{n+1} = (a * X_n  +  c) modulo m

Константы a, c и m выбираются с учетом непредсказуемых последовательностей. X_0 - случайное начальное значение. Существует множество других алгоритмов, но этого, вероятно, достаточно, чтобы начать работу.

Действительно хорошие генераторы псевдослучайных чисел более сложны, такие как Twister Mersenne.

Поправьте меня, если я ошибаюсь, но, хотя этот ответ указывает на часть реализации, я обнаружил, что это еще не все. rand()используется в , который из [glibc][2]. Из версии 2.32, полученной отсюда, stdlibпапка содержит random.cфайл, который объясняет, что используется простой линейный конгруэнтный алгоритм. В папке также есть rand.cа также rand_r.cкоторый может показать вам больше исходного кода. stdlib.hсодержащиеся в той же папке, покажут вам значения, используемые для макросов, таких как RAND_MAX.

/* Улучшенный пакет генерации случайных чисел. В дополнение к стандартному интерфейсу, подобному rand()/srand(), этот пакет также имеет специальный интерфейс информации о состоянии. Подпрограмма initstate() вызывается с начальным значением, массивом байтов и количеством переданных байтов; затем этот массив инициализируется, чтобы содержать информацию для генерации случайных чисел с таким количеством информации о состоянии. Хорошие размеры для объема информации о состоянии: 32, 64, 128 и 256 байт. Состояние можно изменить, вызвав функцию setstate() с тем же массивом, который был инициализирован с помощью initstate(). По умолчанию пакет работает со 128 байтами
информации о состоянии и генерирует гораздо более качественные случайные числа, чем линейный пакет.
конгруэнтный генератор. Если объем информации о состоянии меньше 32 байт, используется простой линейный конгруэнтный ГСЧ. Внутри информация о состоянии обрабатывается как массив длинных значений; нулевой элемент массива — это тип используемого ГСЧ (маленькое целое число); остальная часть массива представляет собой информацию о состоянии для ГСЧ. Таким образом, 32 байта информации о состоянии дадут информацию о состоянии размером 7 длин, что позволит получить полином седьмой степени. (Примечание: нулевое слово состояния
информация также содержит некоторую другую информацию, хранящуюся в ней; подробности см. в setstate). Метод генерации случайных чисел представляет собой подход с линейным регистром сдвига с обратной связью, в котором используются трехчлены (поскольку таким образом можно суммировать меньше членов). При таком подходе младший значащий бит всех чисел в таблице состояний будет действовать как регистр сдвига с линейной обратной связью и будет иметь период 2^deg - 1(где deg — степень используемого полинома, при условии, что полином неприводим и примитивен). Биты более высокого порядка будут иметь более длинные периоды, поскольку на их значения также влияют псевдослучайные переносы младших битов. Общий
период генератора приблизительно равен град*(2град - 1); Таким образом, удвоение объема информации о состоянии оказывает огромное влияние на
период генератора. Примечание. Градус *(2
градус - 1) является приблизительным значением, подходящим только для больших градусов, когда период сдвигового регистра является доминирующим фактором. Когда deg равен семи, период на самом деле намного длиннее, чем 7*(2**7 - 1), предсказанный этой формулой. */

Другие вопросы по тегам