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()
.
이제 "좋아, 그럼 어떻게 덱을 섞지?"라고 말할 수 있습니다. 그 대답-지금 한 이상 rand
과 srand
우려는-어느 정도입니다.
그래서 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
'ProgramingTip' 카테고리의 다른 글
Python에 개체 고유 식별자가 있습니까? (0) | 2020.10.29 |
---|---|
템플릿 클래스를 typedef하는 방법은 무엇입니까? (0) | 2020.10.29 |
모델과 관련이없는 rails simple_form 필드 (0) | 2020.10.29 |
동일한 키를 가진 개체가 ObjectStateManager에 이미 있습니다. (0) | 2020.10.29 |
몽구스, 배열의 값 업데이트 (0) | 2020.10.29 |