source

C에서 랜덤 int를 생성하는 방법

factcode 2022. 8. 27. 09:24
반응형

C에서 랜덤 int를 생성하는 방법

C에 랜덤 int 번호를 생성하는 기능이 있나요?아니면 서드파티 라이브러리를 사용해야 합니까?

주의: 사용하지 않음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에서는 랜덤 및 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;
  }
}

안전한 랜덤 문자 또는 정수가 필요한 경우:

다양한 프로그래밍 언어로 난수를 안전하게 생성하는 방법에서 설명한 바와 같이 다음 중 하나를 수행합니다.

  • 립소듐 사용randombytes
  • Libsodium의 sysrandom 구현에서 필요한 것을 매우 신중하게 재실장할 수 있습니다.
  • 보다 넓게는, 를 사용합니다./dev/random OpenSSL 다른 PRNG이 . 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()암호학적으로 안전하고 편견이 없습니다

최근 응용 프로그램에서 의사 난수 생성기에 심각한 문제가 발생했습니다.Python 스크립트를 사용하여 C 프로그램을 반복해서 호출하여 다음 코드를 시드하고 있었습니다.

srand(time(NULL))

단, 그 이유는 다음과 같습니다.

  • 합니다('rand' srand' 참조).man srand
  • 한 바와 같이 두 와 두 번째만 번되면 두 번째가 됩니다. 같은 초 안에 여러 번 응용 프로그램을 실행하는 경우,time는 매번 같은 값을 반환합니다.

내 프로그램에서도 같은 숫자의 시퀀스가 생성되었다.이 문제를 해결하려면 다음 세 가지 작업을 수행할 수 있습니다.

  1. 실행 시 변경되는 일부 다른 정보와 혼합 시간 출력(내 응용 프로그램에서는 출력 이름):

    srand(time(NULL) | getHashOfString(outputName))
    

    해시함수로 djb2를 사용했습니다.

  2. 시간 분해능을 높입니다.에서는 ★★★★★★★★★★★★★★★★★★★★★★★★★clock_gettime사용할 수 있었기 때문에 사용하고 있습니다.

    #include<time.h>
    struct timespec nanos;
    clock_gettime(CLOCK_MONOTONIC, &nanos)
    srand(nanos.tv_nsec);
    
  3. 두 가지 방법을 함께 사용합니다.

    #include<time.h>
    struct timespec nanos;
    clock_gettime(CLOCK_MONOTONIC, &nanos)
    srand(nanos.tv_nsec | getHashOfString(outputName));
    

옵션 3은 최상의 시드 랜덤성을 보장하지만 매우 빠른 애플리케이션에서만 차이가 발생할 수 있습니다.내 생각에 옵션 2가 안전한 것 같다.

이걸 살펴보자. ''를 사용하겠습니다.srand()함수를 사용하여 랜덤라이저를 시드합니다. generate 、 음 、 음 、 음 、 음 、 numbers 、 numbers 、 basically 、 basically 、 basically 、 basically 、 numbers 、 numbers basically 、 basically basically basically 。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;
    }

시스템에서 기능 패밀리를 지원하는 경우 표준 기능 대신 이러한 기능을 사용할 것을 권장합니다.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_bufbuf : void *콘텐츠의 양은 다음 항목에 따라 결정됩니다.bytes : size_t파라미터를 지정합니다.

arc4random_uniform은 " 없음"입니다.0 <= arc4random_uniform(limit) < limit한계

arc4random_stir/dev/urandomarc4random_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 sizeof(long) bytes (usually 8) into *buf, which points to buf_impl */
  read(urandom_fd, buf, sizeof(long));
  return buf_impl;
}

urandom_init이 " " 를 ./dev/urandom및 를 device에 합니다.urandom_fd.

urandom 함수는 으로 '콜'과 같습니다.rand 보다 한 것을 하고, 「 」, 「 」, 「 」, 「 long(서양속담, 친구속담)

★★★★★★★★★★★★★★./dev/urandom는 약간 느릴 수 있으므로 다른 난수 생성기의 시드로 사용할 것을 권장합니다.

에 음음음음음이 /dev/urandom,/dev/random파일을 하여 단순히 할 수 있습니다.openurandom_init에서 urandom_init ★★★★★★★★★★★★★★★★★」urandom준거하고 있기 가 아닌 합니다.

주의: 다음에서 읽은 내용/dev/urandom사용 가능한 엔트로피가 부족하면 차단되지 않으므로 이러한 상황에서 생성된 값은 암호학적으로 안전하지 않을 수 있습니다.그게 걱정되신다면/dev/random엔트로피가 부족할 경우 항상 차단됩니다.

을 하고 있는 는, 「Windows」를 합니다.rand또는 일부 내부 Windows 전용 플랫폼 의존 비포터블 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;
}

「」보다 .stdlibMersenne Twister를 보세요.그것도 빨라요.예를 들어, 구현 예는 풍부합니다.

C 는 "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가 정수나 플로트로 변환하는 방법을 모방하려고 합니다.

정수의 경우 모듈로 편향을 피하려고 합니다.예를 들어 랜덤한 4자리 정수가rand() % 10000rand()0 ~ 32767 입니다.0에서 2767까지의 보다 더 자주 . 다시 시도하면 .rand()2768 ~32767 의 30000 값이 0 ~9999 의 10000 값에 균일하게 매핑되기 때문에, 값은 2768 이하의 값입니다.

의 경우 비트가 합니다. a는 53개의 랜덤 비트이기 입니다.double는 53비트의 정밀도를 유지합니다(IEEE 더블이라고 가정).53비트 이상을 사용하면 반올림 바이어스가 발생합니다.은 코드를 .rand() / (double)RAND_MAXrand()31번입니다.Windows 에비15 비 windows windows 。

OpenSSL †RAND_bytes() 그 자체, 읽음으로써/dev/urandomLinux 의 linux 。가 많이 하게 되면 수 요./dev/urandom이치노OpenSSL이 시드로부터 더 많은 랜덤 번호를 생성할 수 있도록 하는 것이 더 빠릅니다.

난수에 대한 자세한 정보:

가 아니라 C에 무엇을 모르겠습니다.STL 라 C 、 C + + 。 C가 한 경우에는 C가 .rand() ★★★★★★★★★★★★★★★★★」srand()★★★★

int rand(void);

void srand(unsigned seed);

ANSI C로 하다 ,도 있어요.random()★★★★

long random(void);

내가로는, '아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 네!random()C가 .서드파티 라이브러리는 나쁘지 않은 아이디어일 수 있지만, 이 모든 것은 실제로 얼마나 랜덤한 번호를 생성해야 하는지에 달려 있습니다.

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 사이에서 랜덤한 수를 생성할 수 있습니다.

즉, lower Limit은 포함하거나 r [ [ lower Limit 、 upper Limit ]라고 입력합니다.

이 권해도rand()게 좋아요, 안 쓰려고 요.rand()꼭 해야 하는 게 아니라면!「」가 되는 .rand()생산물은 종종 매우 나쁘다.Linux man:

rand() ★★★★★★★★★★★★★★★★★」srand() C 합니다.random(3) ★★★★★★★★★★★★★★★★★」srandom(3)따라서 하위 비트는 상위 비트만큼 랜덤해야 합니다.단, 오래된 rand() 실장 및 다른 시스템의 현재 실장에서는 하위 비트가 상위 비트보다 훨씬랜덤합니다.적절한 무작위성이 필요할 때 휴대할 수 있도록 설계된 응용 프로그램에서는 이 기능을 사용하지 마십시오.(대신 사용).

에 대해서는, 「 」random()포식스 rand()의 POSIXIEEE 되어 있습니다만, POSIX.1 사양(IEEEE 규격 1003.1-1988)에서는,random()POSIX.1-2001(IEEE 1003.1-2001)은 POSIX.1-2008(IEEE 1003.1-2008, 2016)이다. 저는 그 so so는 、 나는 、 。random()휴대성이 뛰어납니다.

에서는 'POSIX.1-2001'도 되었습니다.lrand48() ★★★★★★★★★★★★★★★★★」mrand48()기능, 여기를 참조해 주세요.

이 함수군은 선형 합동 알고리즘과 48비트 정수 산술을 사용하여 의사 난수를 생성해야 한다.

꽤 는 '가짜 랜덤 소스'입니다.arc4random()많은 시스템에서 사용할 수 있는 기능입니다.규격의 및1997 BSD와 같은 수 .

최신 x86_64 CPU에서는 하드웨어 난수 생성기를 사용하여

코드 예:

#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

이것은 당신이 선택한 두 숫자 사이에서 난수를 얻는 좋은 방법입니다.

#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어떤 숫자를 선택하든, 그러면 이 두 숫자 사이에 랜덤한 숫자가 생성됩니다.

#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;
}

아이작(Indirection, Shift, Acumulate, Add, Count)을 살펴보십시오.균등하게 분포되어 있으며 평균 사이클 길이는 2^8295입니다.

방법은 그냥 하시는 것보다 더하실 수 좋겠습니다.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());
}

C 에 STL c c c 。요.rand 것은, 「」입니다.random은 표준 헤더에 stdlib.hrand POSIX,randomBSD를 사용하다

「 」의 rand ★★★★★★★★★★★★★★★★★」random라는 것이다.random는 훨씬 더하고 "32비트 난수"를 반환합니다.rand열여섯 살는 BSD의 manpages의 가 BSD의 manpages의 비트를 .rand가능하기 에 '예측할 수 있다'는 것입니다.rand이치노

랜덤 문자를 생성하여 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 ;
}

하려고 합니다.rand(). 참고(매우 중요): 랜드 함수의 시드를 설정해야 합니다.그렇지 않으면 난수가 실제로 랜덤이 아닙니다.이건 아주, 아주, 아주, 아주 중요합니다.다행히 일반적으로 시스템틱 타이머와 날짜를 조합하여 사용하면 좋은 시드를 얻을 수 있습니다.

#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;
}

은 범위 .[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));
} 

위에서 언급한 몇 가지 개념에서 조합한 것입니다.

/*    
Uses the srand() function to seed the random number generator based on time value,
then returns an integer in the range 1 to max. Call this with random(n) where n is an integer, and you get an integer as a return value.
 */

int random(int max) {
    srand((unsigned) time(NULL));
    return (rand() % max) + 1;
}

매달림 포인터의 개념을 사용할 수 있습니다.

삭제(또는 해방)된 메모리 위치를 가리키는 포인터를 당글링 포인터라고 합니다.

인쇄 중에 임의의 값이 표시됩니다.

FWIW가 , 'FWIW'가 있다.stdlib.h function함수라고 하는 rand; 이 기능은 주로 속도와 분배를 위해 조정되며, 예측 불가능성을 위해 조정되지 않습니다.다양한 언어 및 프레임워크에 대한 거의 모든 내장 랜덤 함수가 기본적으로 이 함수를 사용합니다.예측성은 떨어지지만 실행 속도는 훨씬 느린 "암호화" 난수 생성기도 있습니다.이것들은, 시큐러티 관련의 모든 애플리케이션에 사용할 필요가 있습니다.

rand()난수를 생성하는 가장 편리한 방법입니다.

당신은 또한 random.org과 같은 온라인 서비스에서 임의의 번호를 얻을 수 있다.

#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()일정한 범위에서 균등하게 분포된 난수를 생성하는 것은 좋지 않은 생각이고, 저는 출력이 실제로 얼마나 왜곡되어 있는지 살펴보기로 했습니다.내 테스트 케이스는 공정한 주사위 던지기였다.다.

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

int main(int argc, char *argv[])
{
    int i;
    int dice[6];

    for (i = 0; i < 6; i++) 
      dice[i] = 0;
    srand(time(NULL));

    const int TOTAL = 10000000;
    for (i = 0; i < TOTAL; i++)
      dice[(rand() % 6)] += 1;

    double pers = 0.0, tpers = 0.0;
    for (i = 0; i < 6; i++) {
      pers = (dice[i] * 100.0) / TOTAL;
      printf("\t%1d  %5.2f%%\n", dice[i], pers);
      tpers += pers;
    }
    printf("\ttotal:  %6.2f%%\n", tpers);
}

출력은 다음과 같습니다.

 $ gcc -o t3 t3.c
 $ ./t3 
        1666598  16.67%     
        1668630  16.69%
        1667682  16.68%
        1666049  16.66%
        1665948  16.66%
        1665093  16.65%
        total:  100.00%
 $ ./t3     
        1667634  16.68%
        1665914  16.66%
        1665542  16.66%
        1667828  16.68%
        1663649  16.64%
        1669433  16.69%
        total:  100.00%

난수가 얼마나 균일해야 하는지는 모르겠지만, 위의 것은 대부분의 요구에 충분히 균일한 것 같습니다.

를 PRNG보다 더 하는 것이 .time(NULL).

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;
    }
}

이다.rand()

이 min인 하여 min이 min이다.INT_MIN 는 " " " 입니다.INT_MAX하지 않습니다.rand()「」로부터 에, 입니다.0로로 합니다.RAND_MAX ( , (1/2 범위), , (1/2 범위).

다음과 같이 사용합니다.

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);

정의 및 doxygen 설명:

#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;
}

다음 항목도 참조하십시오.

  1. [상기 답변을 쓴 후 이 Q&A를 발견했는데, 분명히 매우 관련성이 있고, 비스케일링 레인지 케이스와 같은 작업을 하고 있습니다]rand()에서 특정 범위의 숫자를 얻으려면 어떻게 해야 합니까?
  2. [계수만 사용하지 않고 랜덤성을 유지하는 데 좋은 점이 있는 것 같습니다]rand()에서 특정 범위의 숫자를 얻으려면 어떻게 해야 합니까?
    1. http://c-faq.com/lib/randrange.html

예를 들어 128의 안전한 랜덤비트가 필요한 경우 RFC 1750 준거 솔루션은 사용 가능한 엔트로피 비트(회전 디스크 등)를 생성하는 것으로 알려진 하드웨어 소스를 읽는 것입니다.또한 적절한 구현에서는 혼합 함수를 사용하여 여러 소스를 결합하고 마지막으로 출력을 재매핑 또는 삭제하여 출력의 분포를 디스키핑해야 합니다.

그 이상의 비트가 필요한 경우 128개의 안전한 랜덤비트로 시작하여 원하는 길이로 확장하여 사람이 읽을 수 있는 텍스트에 매핑하는 등의 작업을 수행합니다.

C에서 안전한 난수를 생성하려면 다음 소스코드를 따릅니다.

https://wiki.sei.cmu.edu/confluence/display/c/MSC30-C.+Do+not+use+the+rand%28%29+function+for+generating+pseudorandom+numbers

Windows BCryptGenRandom에서는 과거 20년 이내에 안전하지 않게 된 CryptGenRandom이 아닌 CryptGenRandom이 사용됩니다.BCryptGenRandom이 RFC 1750에 준거하고 있는 것을 확인할 수 있습니다.

Ubuntu(Linux의 플레이버) 등 POSIX 준거 운영체제에서는/dev/urandom ★★★★★★★★★★★★★★★★★」/dev/randomRFC 1750에 준거한 방법으로 여러 소스를 조합하여 엔트로피의 비트를 생성하는 디바이스에 대한 파일형 인터페이스입니다.로부터, 「파일」로 수 .read ★★★★★★★★★★★★★★★★★」fread다른 파일들과 마찬가지로, 하지만 메모는/dev/random수 있을 , 「Native Bits of the new bits of entropy」는 「Native Bits of the new bits of endropy」를 사용할 수 있을 때까지 블록합니다./dev/urandom보안 문제가 될 수 있습니다.풀의 으로, 그를 회피할 수 .entropy_avail 「」를 사용해 .ioctl.

언급URL : https://stackoverflow.com/questions/822323/how-to-generate-a-random-int-in-c

반응형