Как сгенерировать случайный int в C?
Есть ли функция для генерации случайного целого числа в C? Или мне придется использовать стороннюю библиотеку?
32 ответа
Примечание: не используйте
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.
rand()
функция в <stdlib.h>
возвращает псевдослучайное целое число от 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;
}
}
Если вам нужны безопасные случайные символы или целые числа:
Что касается того, как безопасно генерировать случайные числа на разных языках программирования, вам нужно выполнить одно из следующих действий:
- Используйте libsodium 's
randombytes
API - Реализуйте то, что вам нужно, от реализации sysrandom в libsodium, очень осторожно
- В более широком смысле, используйте
/dev/urandom
не/dev/random
, Не OpenSSL (или другие PRNG пользовательского пространства).
Например:
#include "sodium.h"
int foo()
{
char myString[32];
uint32_t myInt;
if (sodium_init() < 0) {
/* panic! the library couldn't be initialized, it is not safe to use */
return 1;
}
/* myString will be an array of 32 random bytes, not null-terminated */
randombytes_buf(myString, 32);
/* myInt will be a random number between 0 and 9 */
myInt = randombytes_uniform(10);
}
randombytes_uniform()
криптографически безопасен и непредвзят.
Давайте пройдем через это. Сначала мы используем функцию srand() для заполнения рандомизатора. По сути, компьютер может генерировать случайные числа на основе числа, которое передается в srand(). Если вы дали одинаковое начальное значение, то каждый раз будут генерироваться одни и те же случайные числа.
Следовательно, мы должны заполнить рандомизатор значением, которое всегда меняется. Мы делаем это, передавая значение текущего времени с помощью функции time().
Теперь, когда мы вызываем rand(), каждый раз будет создаваться новое случайное число.
#include <stdio.h>
int random_number(int min_num, int max_num);
int main(void)
{
printf("Min : 1 Max : 40 %d\n", random_number(1,40));
printf("Min : 100 Max : 1000 %d\n",random_number(100,1000));
return 0;
}
int random_number(int min_num, int max_num)
{
int result = 0, low_num = 0, hi_num = 0;
if (min_num < max_num)
{
low_num = min_num;
hi_num = max_num + 1; // include max_num in output
} else {
low_num = max_num + 1; // include max_num in output
hi_num = min_num;
}
srand(time(NULL));
result = (rand() % (hi_num - low_num)) + low_num;
return result;
}
Если вам нужны псевдослучайные числа лучшего качества, чем какие stdlib
обеспечивает, проверьте Мерсенна Твистера. Это тоже быстрее. Пример реализации в изобилии, например, здесь.
Стандартная функция C rand()
, Это достаточно хорошо, чтобы раздавать карты для пасьянса, но это ужасно. Многие реализации rand()
цикл по короткому списку чисел, и младшие биты имеют более короткие циклы. То, как некоторые программы называют rand()
ужасно, и вычисление хорошего семени, чтобы передать srand()
трудно.
Лучший способ генерировать случайные числа в C - использовать стороннюю библиотеку, такую как OpenSSL. Например,
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <openssl/rand.h>
/* Random integer in [0, limit) */
unsigned int random_uint(unsigned int limit) {
union {
unsigned int i;
unsigned char c[sizeof(unsigned int)];
} u;
do {
if (!RAND_bytes(u.c, sizeof(u.c))) {
fprintf(stderr, "Can't get random bytes!\n");
exit(1);
}
} while (u.i < (-limit % limit)); /* u.i < (2**size % limit) */
return u.i % limit;
}
/* Random double in [0.0, 1.0) */
double random_double() {
union {
uint64_t i;
unsigned char c[sizeof(uint64_t)];
} u;
if (!RAND_bytes(u.c, sizeof(u.c))) {
fprintf(stderr, "Can't get random bytes!\n");
exit(1);
}
/* 53 bits / 2**53 */
return (u.i >> 11) * (1.0/9007199254740992.0);
}
int main() {
printf("Dice: %d\n", (int)(random_uint(6) + 1));
printf("Double: %f\n", random_double());
return 0;
}
Почему так много кода? Другие языки, такие как Java и Ruby, имеют функции для случайных целых чисел или чисел с плавающей точкой. OpenSSL дает только случайные байты, поэтому я пытаюсь имитировать, как Java или Ruby преобразуют их в целые числа или числа с плавающей точкой.
Для целых чисел мы хотим избежать смещения по модулю. Предположим, что мы получили несколько случайных четырехзначных чисел из rand() % 10000
, но rand()
можно вернуть только от 0 до 32767 (как это происходит в Microsoft Windows). Каждое число от 0 до 2767 будет появляться чаще, чем каждое число от 2768 до 9999. Чтобы устранить смещение, мы можем повторить rand()
в то время как значение ниже 2768, потому что 30000 значений от 2768 до 32767 равномерно отображаются на 10000 значений от 0 до 9999.
Для поплавков мы хотим 53 случайных бита, потому что double
содержит 53 бита точности (при условии, что это двойной стандарт IEEE). Если мы используем более 53 бит, мы получаем смещение округления. Некоторые программисты пишут такой код rand() / (double)RAND_MAX
, но rand()
может вернуть только 31 бит или только 15 бит в Windows.
OpenSSL, RAND_bytes()
Семена себя, возможно, читая /dev/urandom
в линуксе Если нам нужно много случайных чисел, было бы слишком медленно читать их все из /dev/urandom
потому что они должны быть скопированы из ядра. Это позволяет OpenSSL генерировать больше случайных чисел из начального числа.
Подробнее о случайных числах:
- Perl Perl_seed() является примером того, как рассчитать начальное число в C для
srand()
, Он смешивает биты из текущего времени, идентификатора процесса и некоторых указателей, если он не может прочитать/dev/urandom
, - Arc4random_uniform () в OpenBSD объясняет смещение по модулю.
- Java API для java.util.Random описывает алгоритмы для удаления смещения из случайных целых чисел и упаковки 53 битов в случайные числа с плавающей точкой.
Если ваша система поддерживает arc4random
Семейство функций, которые я бы рекомендовал использовать вместо стандартных rand
функция.
arc4random
семья включает в себя:
uint32_t arc4random(void)
void arc4random_buf(void *buf, size_t bytes)
uint32_t arc4random_uniform(uint32_t limit)
void arc4random_stir(void)
void arc4random_addrandom(unsigned char *dat, int datlen)
arc4random
возвращает случайное 32-разрядное целое число без знака.
arc4random_buf
помещает случайный контент в свой параметр buf : void *
, Количество контента определяется bytes : size_t
параметр.
arc4random_uniform
возвращает случайное 32-разрядное целое число без знака, соответствующее правилу: 0 <= arc4random_uniform(limit) < limit
где предел также является 32-разрядным целым числом без знака.
arc4random_stir
читает данные из /dev/urandom
и передает данные arc4random_addrandom
дополнительно рандомизировать его внутренний пул случайных чисел.
arc4random_addrandom
используется arc4random_stir
заполнить его внутренний пул случайных чисел в соответствии с данными, переданными ему.
Если у вас нет этих функций, но вы работаете в Unix, вы можете использовать этот код:
/* This is C, not C++ */
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#include <stdlib.h> /* exit */
#include <stdio.h> /* printf */
int urandom_fd = -2;
void urandom_init() {
urandom_fd = open("/dev/urandom", O_RDONLY);
if (urandom_fd == -1) {
int errsv = urandom_fd;
printf("Error opening [/dev/urandom]: %i\n", errsv);
exit(1);
}
}
unsigned long urandom() {
unsigned long buf_impl;
unsigned long *buf = &buf_impl;
if (urandom_fd == -2) {
urandom_init();
}
/* Read 4 bytes, or 32 bits into *buf, which points to buf_impl */
read(urandom_fd, buf, sizeof(long));
return buf_impl;
}
urandom_init
Функция открывает /dev/urandom
устройство, и помещает дескриптор файла в urandom_fd
,
urandom
функция в основном такая же, как вызов rand
, кроме более безопасного, и он возвращает long
(легко меняется).
Тем не мение, /dev/urandom
может быть немного медленным, поэтому рекомендуется использовать его в качестве начального числа для другого генератора случайных чисел.
Если ваша система не имеет /dev/urandom
, но есть /dev/random
или аналогичный файл, то вы можете просто изменить путь к open
в urandom_init
, Вызовы и API, используемые в urandom_init
а также urandom
являются (я считаю) POSIX-совместимыми и поэтому должны работать на большинстве, если не на всех POSIX-совместимых системах.
Примечания: чтение из /dev/urandom
НЕ будет блокироваться при недостаточной энтропии, поэтому значения, сгенерированные при таких обстоятельствах, могут быть криптографически небезопасными. Если вы беспокоитесь об этом, используйте /dev/random
, который всегда будет блокировать при недостаточной энтропии.
Если вы находитесь в другой системе (например, Windows), то используйте rand
или какой-то внутренний непереносимый API-интерфейс, зависящий от платформы.
Функция обертки для urandom
, rand
, или же arc4random
звонки:
#define RAND_IMPL /* urandom(see large code block) | rand | arc4random */
int myRandom(int bottom, int top){
return (RAND_IMPL() % (top - bottom)) + bottom;
}
STL не существует для C. Вы должны позвонить rand
или еще лучше, random
, Они объявлены в заголовке стандартной библиотеки stdlib.h
, rand
это POSIX, random
является функцией спецификации BSD.
Разница между rand
а также random
в том, что random
возвращает гораздо более подходящее 32-битное случайное число, и rand
обычно возвращает 16-битное число. Страницы BSD показывают, что младшие биты rand
являются циклическими и предсказуемыми, поэтому rand
потенциально бесполезен для небольших чисел.
Посмотрите на ISAAC (Indirection, Shift, Accumulate, Add и Count). Он равномерно распределен и имеет среднюю продолжительность цикла 2^8295.
Это хороший способ получить случайное число между двумя числами по вашему выбору.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define randnum(min, max) \
((rand() % (int)(((max) + 1) - (min))) + (min))
int main()
{
srand(time(NULL));
printf("%d\n", randnum(1, 70));
}
Выходной первый раз: 39
Выходной второй раз: 61
Выходной третий раз: 65
Вы можете изменить значения после randnum
на любые номера, которые вы выбираете, и он будет генерировать случайное число для вас между этими двумя числами.
У меня была серьезная проблема с генератором псевдослучайных чисел в моем недавнем приложении: я неоднократно вызывал свою программу на C через скрипт pyhton, и я использовал в качестве семени следующий код:
srand(time(NULL))
Тем не менее, так как:
- rand сгенерирует ту же псевдослучайную последовательность, что и srand (см.
man srand
); - Как уже говорилось, функция времени изменяется только секунда от секунды: если ваше приложение запускается несколько раз в течение одной секунды,
time
будет возвращать одно и то же значение каждый раз.
Моя программа генерировала ту же последовательность чисел. Вы можете сделать 3 вещи, чтобы решить эту проблему:
смешать вывод времени с некоторой другой информацией, изменяющейся при выполнении (в моем приложении имя вывода):
srand(time(NULL) | getHashOfString(outputName))
Я использовал djb2 в качестве хэш-функции.
Увеличьте разрешение по времени. На моей платформе
clock_gettime
был доступен, поэтому я использую его:#include<time.h> struct timespec nanos; clock_gettime(CLOCK_MONOTONIC, &nanos) srand(nanos.tv_nsec);
Используйте оба метода вместе:
#include<time.h> struct timespec nanos; clock_gettime(CLOCK_MONOTONIC, &nanos) srand(nanos.tv_nsec | getHashOfString(outputName));
Вариант 3 гарантирует вам (насколько мне известно) лучшую начальную случайность, но это может создать разницу только в очень быстром приложении. На мой взгляд, вариант 2 - безопасная ставка.
Ну, STL - это C++, а не C, поэтому я не знаю, что вы хотите. Если вы хотите C, однако, есть rand()
а также srand()
функции:
int rand(void);
void srand(unsigned seed);
Они оба являются частью ANSI C. Существует также random()
функция:
long random(void);
Но, насколько я могу судить, random()
не является стандартом ANSI C. Сторонняя библиотека может быть неплохой идеей, но все зависит от того, насколько случайным образом число вам действительно нужно сгенерировать.
Надеюсь, это немного более случайно, чем просто использование srand(time(NULL))
,
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv)
{
srand((unsigned int)**main + (unsigned int)&argc + (unsigned int)time(NULL));
srand(rand());
for (int i = 0; i < 10; i++)
printf("%d\n", rand());
}
Вы хотите использовать rand()
, Примечание (ОЧЕНЬ ВАЖНО): обязательно установите начальное значение для функции ранда. Если вы этого не сделаете, ваши случайные числа не являются действительно случайными. Это очень, очень, очень важно. К счастью, вы можете использовать некоторую комбинацию таймера системных тиков и даты, чтобы получить хорошее начальное число.
C Программа для генерации случайного числа от 9 до 50
#include <time.h>
#include <stdlib.h>
int main()
{
srand(time(NULL));
int lowerLimit = 10, upperLimit = 50;
int r = lowerLimit + rand() % (upperLimit - lowerLimit);
printf("%d", r);
}
В общем, мы можем генерировать случайное число между lowerLimit и upperLimit-1
то есть lowerLimit включительно или, скажем, r ∈ [ lowerLimit, upperLimit)
FWIW, ответ, что да, есть stdlib.h
функция называется rand
; эта функция настроена в первую очередь на скорость и распределение, а не на непредсказуемость. Почти все встроенные случайные функции для различных языков и сред используют эту функцию по умолчанию. Есть также "криптографические" генераторы случайных чисел, которые гораздо менее предсказуемы, но работают намного медленнее. Их следует использовать в любых приложениях, связанных с безопасностью.
На современных процессорах x86_64 вы можете использовать аппаратный генератор случайных чисел через _rdrand64_step()
Пример кода:
#include <immintrin.h>
uint64_t randVal;
if(!_rdrand64_step(&randVal)) {
// Report an error here: random number generation has failed!
}
// If no error occured, randVal contains a random 64-bit number
Несмотря на все предложения людей rand()
здесь, вы не хотите использовать rand()
если не нужно! Случайные числа, которые rand()
производит часто очень плохо. Чтобы процитировать со страницы руководства Linux:
Версии
rand()
а такжеsrand()
в библиотеке Linux C используйте тот же генератор случайных чисел, что иrandom(3)
а такжеsrandom(3)
поэтому биты младшего разряда должны быть такими же случайными, как биты старшего разряда. Однако в более старых реализациях rand() и в текущих реализациях в разных системах биты младшего разряда намного менее случайны, чем биты старшего разряда. Не используйте эту функцию в приложениях, предназначенных для переноса, когда необходима хорошая случайность. (Используйтеrandom(3)
вместо.)
Что касается портативности, random()
также определяется стандартом POSIX уже довольно давно. rand()
старше, он появился уже в первой спецификации POSIX.1 (IEEE Std 1003.1-1988), тогда как random()
впервые появился в POSIX.1-2001 (IEEE Std 1003.1-2001), но текущий стандарт POSIX уже POSIX.1-2008 (IEEE Std 1003.1-2008), который получил обновление только год назад (IEEE Std 1003.1-2008, Издание 2016 г.). Поэтому я хотел бы рассмотреть random()
быть очень портативным.
POSIX.1-2001 также представил lrand48()
а также mrand48()
функции смотрите здесь:
Это семейство функций должно генерировать псевдослучайные числа с использованием линейного конгруэнтного алгоритма и 48-разрядной целочисленной арифметики.
И довольно хороший псевдослучайный источник arc4random()
функция, которая доступна во многих системах. Не является частью какого-либо официального стандарта, появившегося в BSD в 1997 году, но его можно найти в таких системах, как Linux и macOS/iOS.
#include <stdio.h>
#include <stdlib.h>
void main()
{
int visited[100];
int randValue, a, b, vindex = 0;
randValue = (rand() % 100) + 1;
while (vindex < 100) {
for (b = 0; b < vindex; b++) {
if (visited[b] == randValue) {
randValue = (rand() % 100) + 1;
b = 0;
}
}
visited[vindex++] = randValue;
}
for (a = 0; a < 100; a++)
printf("%d ", visited[a]);
}
rand()
это самый удобный способ генерации случайных чисел.
Вы также можете поймать случайное число с любого онлайн-сервиса, например random.org.
#include <stdio.h>
#include <dos.h>
int random(int range);
int main(void)
{
printf("%d", random(10));
return 0;
}
int random(int range)
{
struct time t;
int r;
gettime(&t);
r = t.ti_sec % range;
return r;
}
#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;
}
Если вам нужно, скажем, 128 безопасных случайных битов, решение, совместимое с RFC 1750, должно считывать аппаратный источник, который, как известно, генерирует полезные биты энтропии (например, вращающийся диск). Еще лучше, хорошие реализации должны комбинировать несколько источников с помощью функции микширования и, наконец, устранять перекос в распределении их вывода, повторно отображая или удаляя выходные данные.
Если вам нужно больше бит, чем это, совместимая вещь - начать с последовательности из 128 безопасных случайных битов и растянуть ее до желаемой длины, сопоставить ее с читаемым человеком текстом и т. Д.
Если вы хотите сгенерировать безопасное случайное число в CI, следуйте исходному коду здесь:
Обратите внимание, что для Windows используется BCryptGenRandom, а не CryptGenRandom, который стал небезопасным за последние два десятилетия. Вы можете сами убедиться, что BCryptGenRandom соответствует RFC 1750.
Для операционных систем, совместимых с POSIX, например Ubuntu (разновидность Linux), вы можете просто читать из или, что является файловым интерфейсом для устройства, которое генерирует биты энтропии путем объединения нескольких источников в соответствии с RFC 1750. Вы можете прочитать желаемое количество байтов из этих "файлов" с помощью
read
или
fread
точно так же, как и любой другой файл, но обратите внимание, что читается из
/dev/random
будет блокироваться до тех пор, пока не будет доступно достаточно новых бит энтропии, тогда как
/dev/urandom
не будет, что может быть проблемой безопасности.
Для приложений 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;
}
}
Вы также можете использовать библиотеку mathgl#include <mgl2/mgl_cf.h>
(правда сначала нужно его установить , я сам установил через MSYS2) с функциейmgl_rnd()
. У него также есть виды распределения, такие как равномерное, гуассовое и многое другое. Его нельзя использовать. Но я не знаю о его характеристике.
Вот мой подход (обертка вокруг
rand()
):
Используйте это так:
const int MIN = 1;
const int MAX = 1024;
// Get a pseudo-random number between MIN and MAX, **inclusive**.
// Seeding of the pseudo-random number generator automatically occurs
// the very first time you call it.
int random_num = utils_rand(MIN, MAX);
Определения и описания доксигена:
#include <assert.h>
#include <stdbool.h>
#include <stdlib.h>
/// \brief Use linear interpolation to rescale, or "map" value `val` from range
/// `in_min` to `in_max`, inclusive, to range `out_min` to `out_max`, inclusive.
/// \details Similar to Arduino's ingenious `map()` function:
/// https://www.arduino.cc/reference/en/language/functions/math/map/
///
/// TODO(gabriel): turn this into a gcc statement expression instead to prevent the potential for
/// the "double evaluation" bug. See `MIN()` and `MAX()` above.
#define UTILS_MAP(val, in_min, in_max, out_min, out_max) \
(((val) - (in_min)) * ((out_max) - (out_min)) / ((in_max) - (in_min)) + (out_min))
/// \brief Obtain a pseudo-random integer value between `min` and `max`, **inclusive**.
/// \details 1. If `(max - min + 1) > RAND_MAX`, then the range of values returned will be
/// **scaled** to the range `max - min + 1`, and centered over the center of the
/// range at `(min + max)/2`. Scaling the numbers means that in the case of scaling,
/// not all numbers can even be reached. However, you will still be assured to have
/// a random distribution of numbers across the full range.
/// 2. Also, the first time per program run that you call this function, it will
/// automatically seed the pseudo-random number generator with your system's
/// current time in seconds.
/// \param[in] min The minimum pseudo-random number you'd like, inclusive. Can be positive
/// OR negative.
/// \param[in] max The maximum pseudo-random number you'd like, inclusive. Can be positive
/// OR negative.
/// \return A pseudo-random integer value between `min` and `max`, **inclusive**.
int utils_rand(int min, int max)
{
static bool first_run = true;
if (first_run)
{
// seed the pseudo-random number generator with the seconds time the very first run
time_t time_now_sec = time(NULL);
srand(time_now_sec);
first_run = false;
}
int range = max - min + 1;
int random_num = rand(); // random num from 0 to RAND_MAX, inclusive
if (range > RAND_MAX)
{
static_assert(
sizeof(long int) > sizeof(int),
"This must be true or else the below mapping/scaling may have undefined overflow "
"and not work properly. In such a case, try casting to `long long int` instead of "
"just `long int`, and update this static_assert accordingly.");
random_num = UTILS_MAP((long int)random_num, (long int)0, (long int)RAND_MAX, (long int)min,
(long int)max);
return random_num;
}
// This is presumably a faster approach than the map/scaling function above, so do this faster
// approach below whenever you don't **have** to do the more-complicated approach above.
random_num %= range;
random_num += min;
return random_num;
}
Вы можете генерировать случайные символы, а затем просматривать их как int :
#include <stdlib.h>
#include <stdio.h>
typedef double rand_type; // change double to int
rand_type my_rand() {
char buff[sizeof(rand_type)];
for (size_t i = 0 ; i < sizeof(rand_type) ; ++i)
buff[i] = (char) rand();
return *(rand_type *) buff;
}
int main() {
int i ; // srand as you want
for (i = 0 ; i < 10 ; ++i)
printf("%g\n", my_rand()); // change %g to %d
return 0 ;
}
Специфическая для glibc функция (которую следует найти в большинстве сред Linux), связанная с этим, выглядит следующим образом:
random()
, или вас может заинтересовать его поточно-безопасная версия. Вы должны инициализировать
struct random_data
с
initstate_r()
перед тем, как передать его
random_r()
.
Вот пример быстрого кода:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
void xxx (void) {
unsigned int seed = (unsigned int) time(NULL);
char rnd_state[17] = {0};
struct random_data rnd_st_buf = {0};
initstate_r(seed, &rnd_state[0], 17, &rnd_st_buf);
for(size_t idx = 0; idx < 8; idx++) {
int32_t rnd_int = 0;
char rnd_seq_str[6] = {0};
random_r(&rnd_st_buf, &rnd_int);
memcpy((char *)&rnd_seq_str[0], (char *)&rnd_int, 4);
printf("random number : 0x%08x, \n", rnd_int);
}
}
Вы можете использовать концепцию висячего указателя.
Указатель, указывающий на участок памяти, который был удален (или освобожден), называется висячим указателем.
Во время печати он будет показывать случайные значения.
Мое минималистичное решение должно работать для случайных чисел в диапазоне [min, max)
, использование srand(time(NULL))
перед вызовом функции.
int range_rand(int min_num, int max_num) {
if (min_num >= max_num) {
fprintf(stderr, "min_num is greater or equal than max_num!\n");
}
return min_num + (rand() % (max_num - min_num));
}