ProgramingTip

srand () — 한 번만 호출하는 이유는 무엇입니까?

bestdevel 2020. 10. 29. 08:24
반응형

srand () — 한 번만 호출하는 이유는 무엇입니까?


이 질문은이 질문의 주석에 관한 것입니다. srand를 초기화하는 권장 방법? 첫 번째 주석은 srand()애플리케이션에서 한 번만 호출해야 합니다. 왜 그래야만하지?


그것은 당신이 달성하려는 것에 달려 있습니다.

무작위 화는 시작 값, 즉 seed 를 수행 합니다.

동일한 시드에 대해 항상 동일한 값 시퀀스를 얻습니다.

임의의 값이 필요할 때마다 시드를 설정하려고 시도하고 시드가 동일한 숫자이면 항상 "랜덤"값을 사용합니다.

Seed는 일반적으로에서와 같이 초인 현재 시간에서 time(NULL)가져 오기 전에 항상 난수를 가져 오기 전에 srand / rand 콤보를 여러 호출하는 한 동일한 숫자를 의미 합니다. 같은 초 .

이 문제를 방지하기 위해 srand는 응용 프로그램 당 한 번만 설정됩니다. 두 응용 프로그램 인스턴스가 같은 시간에 초기화 될지 의심 스럽기 때문에 각 인스턴스는 다른 순서의 난수를 사용합니다.

그러나 그러나 앱을 1 초에 여러 번 사용할 수 있습니다. 그러면 다른 방법으로 앱을 선택해야합니다. 시드 (다른 애플리케이션 인스턴스의 동일한 시퀀스가 ​​사용자가 괜찮은 경우 제외). 그러나 내가 말했듯이 그것은 사용의 응용 프로그램에 따라 복잡하게 많다.

(동일한 시드의 가능성을 최소화 sys/time.h). ( ) 가 필요합니다 .

struct timeval t1;
gettimeofday(&t1, NULL);
srand(t1.tv_usec * t1.tv_sec);

난수는 실제로 의사 난수입니다. 시드가 먼저 설정되어의 각 호출 rand에서 난수 가져오고 내부 상태를 수정하며 새 상태는 다음 rand호출에서 다른 번호를 가져 오는 데 사용 됩니다. 특정 공식이 "무작위 번호"를 생성하는 데 사용되기 때문에 모든 호출 후 특정 시드 값을 설정하면 호출 rand에서 동일한 번호가 반환됩니다. 예를 들어 srand (1234); rand ();동일한 값을 반환합니다. 초기 상태를 시드 값으로 한 번 초기화하면 내부 상태를 설정하지 숫자가 충분한 난수가 생성 srand됩니다.

일반적으로 time (NULL)시드 값을 초기화 할 때 반환 된 초 값을 사용합니다 . srand (time (NULL));루프에 많이 말하십시오 . 그런 다음 루프는 1 초에 두 번 이상 반복 할 수 있으므로 루프의 두 번째 rand호출에서 루프가 루프 내부에서 반복되는 횟수는 반복 되는 것 "무작위 번호"를 반환합니다. 프로그램 시작시 한 번 초기화하면 시드가 한 번 설정되고 rand호출 될 때마다 새 번호가 생성되고 내부 상태가 수정 될 다음 호출 rand은 충분히 임의의 번호를 반환합니다.

예를 들어 http://linux.die.net/man/3/rand 의이 코드는 다음과 가변 됩니다.

static unsigned long next = 1;
/* RAND_MAX assumed to be 32767 */
int myrand(void) {
    next = next * 1103515245 + 12345;
    return((unsigned)(next/65536) % 32768);
}
void mysrand(unsigned seed) {
    next = seed;
}

내부 상태 next는 글로벌로 선언됩니다. myrand호출은 내부 상태를 수정하고 업데이트하며 임의의 숫자를 반환합니다. 의 모든 호출은 myrand다른 next값을 가지 메서드 호출마다 다른 번호를 반환합니다.

mysrand을 구현 살펴보십시오 . 전달하는 시드 값을 설정합니다 next. 따라서 next호출하기 전에 매번 동일한 값 을 설정하면 rand동일한 수식이 적용되어 임의의 값을 반환합니다. 이것은 함수가 무작위로 만들어지기 때문에 제때에.

"무작위 시퀀스"를 생성 할 수 있습니다.


짧은 답변 : 전화가 srand()있다하지 난수 생성기에 대한 "주사위를 말하는"처럼. 카드 더미는 것도 아닙니다. 어쨌든 카드 한 벌을 자르는 것입니다.

이렇게 생각하세요. rand()큰 카드 덱에서 딜을 처리하고, 콜할 때마다 덱 상단에서 다음 카드를 선택하고, 값을주고, 그 카드를 덱 맨 아래로 되돌립니다. (예, "무작위"시퀀스가 잠시 후 반복된다는 것을 의미 합니다 . 하지만 매우 큰 덱입니다 :. 일반적으로 4,294,967,296 장의 카드입니다)

또한 프로그램이 실행될 때마다 게임 상점에서 새로운 카드 팩을 구입 하고 모든 새로운 카드 팩은 항상 동일한 순서를 갖습니다. 따라서 특별한 작업을 수행하지 않는 한 프로그램이 실행될 때마다 동일한 "무작위"숫한 얻습니다 rand().

이제 "좋아, 그럼 어떻게 덱을 섞지?"라고 말할 수 있습니다. 그 대답-지금 한 이상 randsrand우려는-어느 정도입니다.

그래서 srand무엇 ? 제가 여기에서 만든 비유에 따르면, 호출 srand(n)은 기본적으로 " n맨 위에서 카드를 잘라내십시오"라고 말하는 것과 같습니다 . 하지만 한 가지 더 기다려주세요. 실제로 는 다른 새로운 덱으로 시작 n하여 위에서부터 카드를 잘라 냅니다.

당신이 전화를한다면 srand(n), rand(), srand(n), rand(), ...,과 같은 n때마다, 당신은 그냥하지 않은 매우 무작위 순서 를 얻을 수 없습니다 ,은 실제로에서 당신 같은 번호를 다시 얻을 것이다 rand()때마다. (아마도 당신이 건네 준 것과 같은 번호 srand는 관계, 계속해서 같은 번호를 되찾았 rand습니다.)

그래서 당신이 할 수있는 최선 의 방법은 당신의 프로그램이 시작될 때 덱을 한 번 자르는 것 srand()입니다. n즉,으로 무작위적인 합리적 것을 사용하여 한 번 호출 하십시오 . 그래서 당신은 매번 큰 덱의 다른 임의의 장소에서 시작할 것입니다. 프로그램이 실행됩니다. 를 사용하면 rand()정말 최선을 다할 수 있습니다.

[추신 : 네, 실제 생활에서 새로운 카드 덱을 구입하면 일반적으로 순서가 아닌 순서대로 실행합니다. 여기서 비유가 작동하는 게임 상점에서 구입하는 각 덱이 겉보기에는 무작위 순서로되어 같은 상점에서 구입하는 다른 모든 카드 덱과 똑같은 순서로되어 있습니다 상상합니다. 브리지 토너먼트에서 사용하는 똑같이 섞인 카드 덱과 준비합니다.]


그 이유는 srand()랜덤 생성기의 초기 상태 설정하고 생성기가 생성하는 모든 값은 그 사이에 직접 상태를 건드리지 "충분히 랜덤"이기 때문입니다.

예를 들어 다음과 같이 할 수 있습니다.

int getRandomValue()
{
    srand(time(0));
    return rand();
}

그런 다음 time()호출에서 호출에서 반복적으로 호출하여 호출에서 동일한 값 생성합니다. 이는 의도적으로는 것입니다.


srand는 의사 난수 생성기를 시드합니다. 두 번 이상 호출하면 RNG를 다시 시드합니다. 그리고 동일한 인수로 호출하면 동일한 시퀀스가 ​​다시 시작됩니다.

이를 증명하기 위해 다음과 같이 간단한 작업을 수행합니다.

#include <cstdlib>
#include <cstdio>
int main() {
for(int i = 0; i != 100; ++i) {
        srand(0);
        printf("%d\n", rand());
    }
}

같은 번호가 100 번 인쇄 된 것을 볼 수 있습니다.


srand()동일한 초에 실행되는 애플리케이션 인스턴스에 대해 다른 시드를 생성 하는 데 사용하는 더 간단한 솔루션 은 다음과 같습니다.

srand(time(NULL)-getpid());

이 방법은 스레드가 시작된 시간을 추측 할 방법이없고 pid도 다를 것이므로 시드를 무작위에 매우 가깝게 만듭니다.


1 \ rand ()가 실행될 때마다 다음 rand ()에 대한 새 시드를 설정합니다.

2 \ srand ()가 여러 번 실행되는 경우 문제는 두 번의 실행이 1 초에 발생하면 (시간 (NULL)이 변경되지 않음) 다음 rand ()가 이전 rand ()와 동일합니다. srand ().

참고 URL : https://stackoverflow.com/questions/7343833/srand-why-call-it-only-once

반응형