2012-08-08 3 views
3

rand_r에 문제가 있습니다. 수백만 개의 난수를 생성하는 시뮬레이션이 있습니다. 나는 어느 시점에이 수치가 더 이상 일정하지 않다는 것을 알았다. 무엇이 문제 일 수 있습니까?수백만 개의 난수가 생성되었습니다. "오버플로"rand_r?

내가하는 일 : 나는 생성기의 인스턴스를 만들고 자신의 씨앗을 제공합니다.

class nativeRandRUni { 

    public: 
     unsigned seed; 

     nativeRandRUni(unsigned sd){ seed= sd; } 
     float genP() { return (rand_r(&seed))/float(RAND_MAX); } // [0,1] 
     int genI(int R) { return (rand_r(&seed) % R); } // [0,R-1] 
}; 

숫자는 단순히 의해 생성됩니다 :

newIntNumber= mainRGen->genI(desired_max); 
newFloatNumber= mainRGen->genP(); 

시뮬레이션 문제는 위의 설명이 여기

mainRGen= new nativeRandRUni(idumSeed_g); 

클래스/객체 데프이다. 나는 이것이 내가 결과를 서명 (결과를 참조하십시오 상단 이미지, http://ubuntuone.com/0tbfidZaXfGNTfiVr3x7DR)

도 표시됩니다 시간 이후에 생성 된 숫자의 분포를 확인한 원인은 내가 t에서 씨앗을 인쇄하는 경우 -1과 t는 시그니처의 시점이고, 시드 값이 263069042에서 1069048066으로 변하는 것을 볼 수 있습니다.

다른 시드로 코드를 실행하면 문제는 항상 존재하지만 다른 시간 지점에서

또한 내 객체 대신에 rand()를 사용하면 모든 것이 잘됩니다 ... 객체를 사용해야 할 때가 있습니다. 스레드를 사용하는 경우가 있습니다. 위의 예는 스레드가 없습니다.

나는 정말로 여기에서 잃어버린 단서가 있습니까?

편집 - 충분히 시간을 반복하여 재현 할 수 편집
는, 문제는 내가 말했듯이,이 발생하는 문제에 대한 반복의 수백만을 소요한다는 것입니다. 시드 -158342163에 대해 나는 세대 t = 134065568에 그것을 얻는다. 하나는 (유니폼)과 (유니폼이 아닌) 후에 생성 된 번호를 확인할 수 있습니다. 주어진 t에서 수동으로 시드를 변경하면 동일한 문제가 발생합니다 (코드에서 (*) 참조). 나는 또한 일어날 것을 기대하지 않는다?

#include <tr1/random> 
#include <fstream> 
#include <sstream> 
#include <iostream> 

using std::ofstream; 
using std::cout; 
using std::endl; 

class nativeRandRUni { 

    public: 
     unsigned seed; 
     long count; 

     nativeRandRUni(unsigned sd){ seed= sd; count=0; } 
     float genP() { count++; return (rand_r(&seed))/float(RAND_MAX); } // [0,1] 
     int genI(int R) { count++; return (rand_r(&seed) % R); } // [0,R-1] 

}; 

int main(int argc, char *argv[]){ 

    long timePointOfProblem= 134065568; 

    nativeRandRUni* mainRGen= new nativeRandRUni(-158342163); 
    int rr; 

    //ofstream* fout_metaAux= new ofstream(); 
    //fout_metaAux->open("random.numbers"); 
    for(int i=0; i< timePointOfProblem; i++){ 
      rr= mainRGen->genI(1009200); 
      //(*fout_metaAux) << rr << endl; 
      //if(i%1000==0) mainRGen->seed= 111111; //(*) FORCE  
    } 
    //fout_metaAux->close(); 

}  
+1

는이 이상을 표시하는 기능이있는 작은 프로그램을 작성할 수 있습니까? 10' 정도 - – rodrigo

+1

당신은'timePointOfProblem에서 seed''의 가치를 게시 할 수 있을까요? 134mil 반복 작업을하지 않고도 장면 뒤에서 진행되는 작업을 더 빠르게 볼 수 있습니다. –

답변

1

난수가 시뮬레이션의 핵심이라면 자신의 생성기를 구현해야합니다. 나는 rand_r이 어떤 알고리즘을 사용하고 있는지 알지 못하지만 선형 합동 생성기와 같이 꽤 엉터리 일 수있다.

저는 기본 알고리즘을 알고있는 곳에서 빠른 속도와 좋은 품질로 구현하려고합니다. 나는 메르 센 트위스터를 구현보고 시작 했죠 :

http://en.wikipedia.org/wiki/Mersenne_twister

매우 빠르게 구현하기 위해 간단 - 더 분할 할 필요가 없습니다.

+3

휠을 재발 명하기보다는 부스트 또는 C++ 구현을 사용하지 않는 이유는 무엇입니까? –

+1

동의합니다. C++ 11을 사용하는 경우 표준 라이브러리에 전체 난수 생성기 모음이 있습니다. 그렇지 않다면, Boost.Random은 거의 동일한 세트를 가지고 있습니다. –

+0

부스트에 의존하기 위해 문제를 겪고 싶다면 그렇게 할 수 있습니다. 하지만 알고리즘을 완벽하게 제어 할 수는 없습니다. mersenne 트위스터를 구현하는 데 하루가 걸릴 수도 있고 또 다른 날에이를 확인하기위한 통계적 조치를 취할 수도 있습니다. 나는 그랬다. –

1

발전기로 변경, 부스트에서 간단한 솔루션을 시도하고 결국 : 내가 이해하지 못하는 매우 편안하게 해달라고, 난 더 이상이 문제를 얻지 않는다 ... 그것을 해결 그래도

class nativeRandRUni { 
    public: 
     typedef mt19937 EngineType; 
     typedef uniform_real<> DistributionType; 
     typedef variate_generator<EngineType, DistributionType> VariateGeneratorType; 

     nativeRandRUni(long s, float min, float max) : gen(EngineType(s), DistributionType(min, max)) {} 
     VariateGeneratorType gen; 
}; 

무엇 그것은이었다.나는 라파엘 잘 생각, 나는이 이전보다 느린 지금 세대

이 집중적 번호 rand_r을 신뢰하지 않아야, 그래서 그것을 최적화 방법을 보일 수 있습니다. 질문 : 원칙적으로 메르 센 트위스터 구현이 빠를까요? 모든

와 감사합니다!

+1

단순한 RNG는 훨씬 작은 상태에서 작동하므로 일반적으로 더 빠릅니다. 그러나 정확하게 가난한 사람들을 만드는 것은이 작은 국가입니다. Mersenne Twister는 624 개의 정수를 사용합니다. – MSalters

+1

이미 EngineType의'mt19937' 메르 센 트위스터 구현 아닌가? "양호한"의사 ​​난수를 원한다면 작은 성능 비용을 지불 할 준비를해야합니다. –

+0

네, mt19937은 MT입니다. 여러분 중 누가 더 빠른 것을 구현 한 경험이 있는지 궁금합니다. 그것의 ok tho, 나는 지금 행복하다. 감사! – lourencoj

관련 문제