Как сгенерировать случайный int в C?

Как было предложено в , другой ответ здесь , я использовал функцию из комментариев в документации PHP , но обнаружил, что она субоптимальна, трудно читается / поддерживается, и не полностью по сравнению с (несоответствующим) корпусом некоторых заголовков.

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

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

 'DASL',
            'Dav'              => 'DAV',
            'Etag'             => 'ETag',
            'Mime-Version'     => 'MIME-Version',
            'Slug'             => 'SLUG',
            'Te'               => 'TE',
            'Www-Authenticate' => 'WWW-Authenticate',
            // MIME
            'Content-Md5'      => 'Content-MD5',
            'Content-Id'       => 'Content-ID',
            'Content-Features' => 'Content-features',
        );
        $arrHttpHeaders = array();

        foreach($_SERVER as $strKey => $mixValue) {
            if('HTTP_' !== substr($strKey, 0, 5)) {
                continue;
            }

            $strHeaderKey = strtolower(substr($strKey, 5));

            if(0 < substr_count($strHeaderKey, '_')) {
                $arrHeaderKey = explode('_', $strHeaderKey);
                $arrHeaderKey = array_map('ucfirst', $arrHeaderKey);
                $strHeaderKey = implode('-', $arrHeaderKey);
            }
            else {
                $strHeaderKey = ucfirst($strHeaderKey);
            }

            if(array_key_exists($strHeaderKey, $arrCasedHeaders)) {
                $strHeaderKey = $arrCasedHeaders[$strHeaderKey];
            }

            $arrHttpHeaders[$strHeaderKey] = $mixValue;
        }

        return $arrHttpHeaders;

    }
}

512
задан Cœur 14 July 2018 в 16:39
поделиться

10 ответов

Примечание : не используйте rand () для безопасности. Если вам нужен криптографически защищенный номер, см. Этот ответ .

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

srand(time(NULL));   // Initialization, should only be called once.
int r = rand();      // Returns a pseudo-random integer between 0 and RAND_MAX.

Редактировать : В Linux вы можете использовать random и srandom .

641
ответ дан 22 November 2019 в 22:27
поделиться

Для Linux C приложения:

Это - мой переделанный код из ответа выше этого, применяет мои методы кода C и возвращает случайный буфер любого размера (с надлежащими кодами возврата, и т.д.). Удостоверьтесь, что звонили urandom_open() однажды в начале Вашей программы.

int gUrandomFd = -1;

int urandom_open(void)
{
    if (gUrandomFd == -1) {
        gUrandomFd = open("/dev/urandom", O_RDONLY);
    }

    if (gUrandomFd == -1) {
        fprintf(stderr, "Error opening /dev/urandom: errno [%d], strerrer [%s]\n",
                  errno, strerror(errno));
        return -1;
    } else {
        return 0;
    }
}


void urandom_close(void)
{
    close(gUrandomFd);
    gUrandomFd = -1;
}


//
// This link essentially validates the merits of /dev/urandom:
// http://sockpuppet.org/blog/2014/02/25/safely-generate-random-numbers/
//
int getRandomBuffer(uint8_t *buf, int size)
{
    int ret = 0; // Return value

    if (gUrandomFd == -1) {
        fprintf(stderr, "Urandom (/dev/urandom) file not open\n");
        return -1;
    }

    ret = read(gUrandomFd, buf, size);

    if (ret != size) {
        fprintf(stderr, "Only read [%d] bytes, expected [%d]\n",
                 ret, size);
        return -1;
    } else {
        return 0;
    }
}
0
ответ дан Brad Grissom 4 October 2019 в 09:27
поделиться
#include<stdio.h>
#include<stdlib.h>
#include<time.h>

//generate number in range [min,max)
int random(int min, int max){
    int number = min + rand() % (max - min);
    return number; 
}

//Driver code
int main(){
    srand(time(NULL));
    for(int i = 1; i <= 10; i++){
        printf("%d\t", random(10, 100));
    }
    return 0;
}
1
ответ дан 22 November 2019 в 22:27
поделиться

Ну, STL - это C ++, а не C, поэтому я не знаю, что вы хотите. Однако, если вы хотите C, есть функции rand () и srand () :

int rand(void);

void srand(unsigned seed);

Они оба являются частью ANSI C. Существует также случайное () function:

long random(void);

Но, насколько я могу судить, random () не является стандартом ANSI C. Сторонняя библиотека не может быть плохой идеей, но все зависит от насколько случайное число вам действительно нужно сгенерировать.

3
ответ дан 22 November 2019 в 22:27
поделиться

FWIW, ответ: да, есть функция stdlib.h под названием rand ; эта функция настроена в первую очередь на скорость и распределение, а не на непредсказуемость. Почти все встроенные случайные функции для различных языков и сред используют эту функцию по умолчанию. Есть также «криптографические» генераторы случайных чисел, которые гораздо менее предсказуемы, но работают намного медленнее. Их следует использовать в любых приложениях, связанных с безопасностью.

4
ответ дан 22 November 2019 в 22:27
поделиться

Вы хотите использовать rand () . Примечание ( ОЧЕНЬ ВАЖНО ): обязательно установите начальное значение для функции ранда. Если вы этого не сделаете, ваши случайные числа не являются действительно случайными . Это очень, очень, очень важно. К счастью, вы можете использовать некоторую комбинацию системного таймера и даты, чтобы получить хорошее начальное значение.

4
ответ дан 22 November 2019 в 22:27
поделиться

Взгляните на ISAAC (косвенное направление, смещение, накопление, сложение и подсчет). Он равномерно распределен и имеет среднюю продолжительность цикла 2 ^ 8295.

7
ответ дан 22 November 2019 в 22:27
поделиться

STL не существует для C. Вы должны вызвать rand , или еще лучше, случайным образом . Они объявлены в заголовке стандартной библиотеки stdlib.h . rand - это POSIX, random - это спецификация BSD.

Разница между rand и random состоит в том, что random возвращает гораздо более пригодное для использования 32-битное случайное число, а rand обычно возвращает 16-битное число. Страницы BSD показывают, что младшие биты rand являются циклическими и предсказуемыми, поэтому rand потенциально бесполезна для небольших чисел.

8
ответ дан 22 November 2019 в 22:27
поделиться

Функция rand () в возвращает псевдослучайное целое число от 0 до RAND_MAX . Вы можете использовать srand (unsigned int seed) для установки начального числа.

Обычная практика - использовать оператор % в сочетании с rand () для получить другой диапазон (хотя имейте в виду, что это несколько нарушает однородность). Например:

/* random int between 0 and 19 */
int r = rand() % 20;

Если вы действительно заботитесь о единообразии, вы можете сделать что-то вроде этого:

/* Returns an integer in the range [0, n).
 *
 * Uses rand(), and so is affected-by/affects the same seed.
 */
int randint(int n) {
  if ((n - 1) == RAND_MAX) {
    return rand();
  } else {
    // Supporting larger values for n would requires an even more
    // elaborate implementation that combines multiple calls to rand()
    assert (n <= RAND_MAX)

    // Chop off all of the values that would cause skew...
    int end = RAND_MAX / n; // truncate skew
    assert (end > 0);
    end *= n;

    // ... and ignore results from rand() that fall above that limit.
    // (Worst case the loop condition should succeed 50% of the time,
    // so we can expect to bail out of this loop pretty quickly.)
    int r;
    while ((r = rand()) >= end);

    return r % n;
  }
}
231
ответ дан 22 November 2019 в 22:27
поделиться

Если вам нужны псевдослучайные числа лучшего качества, чем то, что предоставляет stdlib , посмотрите Mersenne Twister . Это тоже быстрее. Примеры реализации многочисленны, например здесь .

25
ответ дан 22 November 2019 в 22:27
поделиться
Другие вопросы по тегам:

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