문제

나는 실행당 의사 난수 생성기를 두 번 이상 시딩하지 말라는 권장 사항을 꽤 많이 보았지만 자세한 설명은 전혀 동반되지 않았습니다.물론 다음(C/C++) 예제가 좋은 생각이 아닌 이유를 쉽게 알 수 있습니다.

int get_rand() {
  srand(time(NULL));
  return rand();
}

전화한 이후로 get_rand 초당 여러 번 반복되는 결과가 생성됩니다.

하지만 다음 예는 여전히 수용 가능한 솔루션이 아닐까요?

MyRand.h

#ifndef MY_RAND_H
#define MY_RAND_H

class MyRand
{
  public:
    MyRand();
    int get_rand() const;
  private:
    static unsigned int seed_base;
};

#endif

MyRand.cpp

#include <ctime>
#include <cstdlib>
#include "MyRand.h"

unsigned int MyRand::seed_base = static_cast<unsigned int>(time(NULL));

MyRand::MyRand()
{
  srand(seed_base++);
}

int MyRand::get_rand() const
{
  return rand();
}

메인.cpp

#include <iostream>
#include "MyRand.h"

int main(int argc, char *argv[]) 
{
  for (int i = 0; i < 100; i++) 
  {
    MyRand r;
    std::cout << r.get_rand() << " ";
  }
}

즉.~ 일지라도 MyRand:s 생성자는 빠르게 연속해서 여러 번 호출됩니다. srand 다른 매개변수가 있습니다.분명히 이것은 스레드로부터 안전하지 않지만 역시 마찬가지입니다. rand.

도움이 되었습니까?

해결책

의사 난수 생성기 함수를 호출할 때마다 생성기는 내부 상태를 취하고 의사 난수와 새로운 내부 상태를 생성합니다.내부 상태를 변환하는 알고리즘은 출력이 무작위로 나타나도록 신중하게 선택됩니다.

난수 생성기를 시드하면 기본적으로 이 내부 상태를 설정하게 됩니다.내부 상태를 예측 가능한 값으로 재설정하면 무작위성이 사라집니다.

예를 들어, 널리 사용되는 간단한 RNG는 선형 합동 생성기입니다.숫자는 다음과 같이 생성됩니다.

X[n+1] = (a X[n] + c) mod m

이 경우 X[n+1]은 결과이자 새로운 내부 상태입니다.위에서 제안한 대로 매번 생성기를 시드하면 다음과 같은 시퀀스를 얻게 됩니다.

{(ab + c) mod m, (a(b+1) + c) mod m, (a(b+2) + c) mod m, ...}

b는 어디 있어? seed_base.이것은 전혀 무작위로 보이지 않습니다.

다른 팁

씨앗을 예측할 수있는 경우, 단지 여기에있는 이후 여기에있는 경우 Rand ()의 출력도 예측할 수 있습니다.

실제로 임의의 숫자를 생성하려는 이유와 "무작위"가 당신에게 허용 가능한 임의의 방법에 달려 있습니다. 당신의 예에서, 그것은 빠른 연속으로 복제를 피할 수 있으며, 그것은 당신에게 충분할 수 있습니다. 결국, 중요한 것은 그것이 실행된다는 것입니다.

거의 모든 플랫폼에서는 rand ()보다 난수를 생성하는 더 좋은 방법이 있습니다.

글쎄, 그것은 완료 할 필요가없는 추가 처리입니다.

이 시나리오에서는 루프를 시작하기 전에 시간 기반 씨앗으로 생성자를 한 번 호출합니다. 이는 모든 반복에 대한 교체를 변경하는 여분의 오버 헤드없이 임의의 결과를 보장합니다.

나는 당신의 방법이 어떤 것이라고 생각하지 않을 것입니다 그보다 무작위.

당신은 무작위 숫자 생성을 생각할 수 있습니다 (이것은 더 이상 진실한 구현이 아니라 더 이상 진정한 구현이 아니라 그림으로 작용할 수 있음)을 값 표로 생각할 수 있습니다. 간단한 임의의 샘플을 수행하기 위해 통계 에서이 작업을 수행하는 것을 기억한다면, 씨앗은 기본적으로 큰 임의의 숫자 테이블에서 시작할 행과 열을 알려줍니다. 우리는 이미 숫자가 이미 정상적으로 분포되어 있다고 가정 할 수 있기 때문에 반복해서 다시 재조정하는 것은 불필요합니다.

응용 프로그램에 따라 충분해야하므로 두 번 이상 파종하는 데 추가 이점이 없습니다. "더 많은"랜덤 숫자가 필요하면 많은 무작위 숫자 생성 방법이 있습니다. 내가 생각할 수있는 한 가지 사례는 스레드 안전 방식으로 난수를 생성하는 것입니다.

솔루션은 허용되지만 숫자는 전 세계적으로 한 번 파종하는 것보다 더 무작위가되지 않습니다. Srand는 일반적으로 생성자에 속하지 않아야합니다. 임의의 숫자를 지원하려면 프로그램이 시작될 때 한 번 시드하고 잊어 버리십시오.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top