2011-11-26 4 views
1

효과적으로 난수를 생성하는 방법은 무엇입니까?
난수 프로그램이 부팅 할 때마다 이전과 같은 숫자가 나옵니다. (나는 무작위 수 생성의 준 자연 때문에)
임의의 생성이 비 결정적이되는 방법이 있을까요? 부팅 후 생성 된 숫자가 마지막 순서와 다른 순서로 생성되는 일종의 엔트로피 추가. (임의의 랜덤 오히려 그 의사 - 랜덤)도
는 이러한 생성 범위를 말한다 (m, n)은 나노 = X를, 다수 X-1 개 숫자 후 다음번에 나타나는 'P'을 말하고있는 기회가되도록 생성되었습니다. 그러나 그 다음 x 숫자는 마지막 것과 같은 순서가 아닙니다. 예 :
범위 : 1,5. 세대 : 2,4,5,1,3 (1 번째) 4,2,3,1,5 (2 번째) ... 같은 번호. (1440)
여기효과적으로 난수 생성

int num1 = (rand.Next(1, 440) *31* (int)DateTime.Now.Ticks *59* (DateTime.Now.Second * 100) % 439) + 1; 
int num2 = (rand.Next(1, 440) *31* (int)DateTime.Now.Ticks *59* (DateTime.Now.Second * 100) % 439) + 1; 

범위이었다 : 마음의 nonplussed 상태 중
나는 이것을 썼다. 하지만 그것은 여전히 ​​바운드와 제로의 숫자를 생성하며, 빈도는 그렇게 크지 않습니다. 그것은 C# .NET 코드입니다. 왜 그렇게?
답변은 언어 불가지론/알고리즘/분석 일 수 있습니다. 미리 감사드립니다.

+2

여기를보십시오 : http://msmvps.com/blogs/jon_skeet/archive/2009/11/04/revisiting-randomness.aspx – Tigran

+0

2,4,5,1,3 및 4,2,3은 어떻게 되는가? 1,5 관련 또는 불량? 범위를 소수의 정수 값으로 제한하고 요청한 것을 얻었습니다. –

+0

@HenkHolterman 나는 벗어났다. 'Random rnd = new Random(); '함수를 호출하고 나서 Next() 함수를 사용하려고했습니다. 그 점을 지적 해 주셔서 감사합니다. –

답변

2

거의 "임의의"번호 생성기는 실제로는 무작위입니다. 거의 모든 것은 의사 난수이며, 같은 seed value으로 시작할 때 예상 할 수있는 순서대로 이어집니다. 많은 pseudorandom number generators (PRNGs)는 초기 호출 날짜와 시간부터 시드를 가져옵니다. 다른 사람들은 운영 체제에서 제공하는 임의의 데이터 소스 (예 : , 예 :, 마우스 동작, 키보드 활동)를 통해 외부에서 생성되는 데이터 원본에서 시드를 가져옵니다.

좋은 난수 생성기를 시드하는 올바른 방법은 시드하지 않는 것입니다. 모든 훌륭한 생성기는 시드를 제공하는 기본 메커니즘을 가지고 있으며 일반적으로 여러분이 생각해 낼 수있는 것보다 훨씬 낫습니다.생성기를 시드 할 유일한 이유는 실제로 이 임의의 숫자 시퀀스 (임의성이 필요한 프로세스를 반복하려는 경우 예 :)와 동일한 시퀀스을 원하는 경우입니다.

C# Random 클래스에 대한 자세한 내용은 http://msdn.microsoft.com/en-us/library/system.random.aspx을 참조하십시오. 기본적으로 매우 잘 알려져 있고 존경받는 알고리즘을 사용하며 날짜와 시간을 표시합니다.

rand.Next(min, max+1)를 사용, 키 질문에 대답하려면, 당신은 항상minmax 포함 사이의 숫자의 임의의 순서를 얻을 수 있습니다. 같은 씨앗을 사용할 때마다 순서가 동일합니다. 그러나 rand = new Random()은 현재 시간을 사용하고 프로그램이 약간의 시간 간격으로 호출되는 한 다른 시간대를 사용합니다.

+0

+1 "그러나 rand = new Random()은 현재 시간을 사용하고 프로그램이 약간의 시간 간격으로 호출되는 한 그들은 다를 것입니다." 네, 문제를 일으키고있었습니다. 방금 오늘 아침에 알아 냈어. 'System.Threading.Thread.Sleep (100); '이 트릭을했습니다. –

1

"씨"에 통과 한 후 자정 이후의 시간 (초)을 받고하여 난수 생성기 :

Random rand = new Random(secs); 

이 아직 완벽하게 임의의 숫자를 생성하지 않습니다,하지만 당신의 목적을 제공한다.

+1

이것은 기본적으로 C#이 이미 수행 한 작업입니다 (http://msdn.microsoft.com/en-us/library/system.random.aspx 참조). –

+0

@ 로스 당신 말이 맞을 것 같습니다. 나는 왜 포스터가 동일한 일련의 수를 보는지 확신 할 수 없다. – dnuttle

0

저는 C#에 능숙하지 않습니다. 는하지만 임의의 클래스의 기본 생성자는 현재 시간을 기준으로 종자를 사용하고 고유 카운트 identifier.Below이 java.util.Random의 클래스의 코드 때문에이 문제가 자바에서 발생하는 것입니다 생각하지 않습니다.

private static volatile long seedUniquifier = 8682522807148012L; 
public Random() { this(++seedUniquifier + System.nanoTime()); } 

C#이 상자를 지원하는 경우 위의 코드를 사용하여 매번 고유 한 시드를 만들 수 있습니다.

P.S : seedUniquifier에 대한 액세스가 동기화되지 않기 때문에, 심지어는 휘발성 불구하고, 같은 씨앗은 여러 임의의 객체에 사용되는 작은 가능성이 있습니다. 임의의 클래스의 javadoc에서 :

"이 생성자는이 생성자의 다른 호출에서 구분되어 매우 가능성이 값으로 난수 생성기의 씨앗을 설정합니다."

+0

당신은 "... 자바에서 ** 발생하지 않을 것입니다 ..."라고 생각했습니다. –

+0

C#은 시간 만 사용하므로 추가 요소는 없습니다 (http://msdn.microsoft.com/en-us/library/system.random.aspx 참조). –

+0

그게 실제로 잘못된가요? 휘발성은 rmw - 원 자성을 보장하지 않으므로 동일한 시드를 두 번 얻을 수 있습니다. – harold

1

동일한 시퀀스를 반복해서 생성하는 것은 종종 버그가 아니라 기능인 경우가 많습니다. 반복 가능한 시퀀스를 생성하면 디버깅이 쉬워집니다. 당신이 재현 할 수없는 임의의 시퀀스를 원한다면, 이것을 보안 목표로 삼는 안전한 난수 생성기를 찾을 수 있습니다. 질문 C#을 태그했지만 Java가 http://docs.oracle.com/javase/1.4.2/docs/api/java/security/SecureRandom.html이고 Windows API가 http://en.wikipedia.org/wiki/CryptGenRandom이므로 C#에서 해당 항목을 찾을 수 있습니다.

+1

C#의 암호화 품질 난수는'RNGCryptoServiceProvider.GetBytes()'를 사용하십시오. RFC 4086을 참조하십시오. – rossum

0

혼돈스러운지도를 사용하여 임의의 숫자를 생성 할 수 있습니다. 아래의 C++ 코드 (GenRandRea)는 이른바 "Tent map"(https://www.wikiwand.com/en/Tent_map)을 사용하여 난수 벡터를 반환합니다. 시드는 반복 맵의 입력으로 x (0과 1 사이의 숫자로)를 생성하는 데 사용되는 정수입니다. 다른 씨앗은 다른 순서를 생성합니다.

const double tentmap_r = 0.75; //parameter for the tent map 
const int tentmap_delay = 50; /*number of interactions in the tent map 
           allowing for sorting */ 
const double tentmap_const = 1.e6; //constant for the tent map 

VecDim와

vector<double> GenRandRea(unsigned seed, int VecDim){ 
double x, y, f; 
vector<double> retval; 

x = 0.5*(abs(sin((double)seed)) + abs(cos((double)seed))); 

for (int i = 0; i<(tentmap_delay + VecDim); i++) { 
    if ((x >= 0.) && (x <= 0.5)) { 
     f = 2 * tentmap_r * x; 
    } 
    else { 
     f = 2 * tentmap_r * (1. - x); 
    } 

    if (i>=tentmap_delay) { 
     y = (x*tentmap_const) - (int)(x*tentmap_const); 
     retval.push_back(y); 
    } 
    x = f; 
} 
return retval; 

}

출력 벡터의 차원이다. 이상 (tentmap_delay + VecDim)은 적어도 반복하여 결과를 retval (복식의 벡터)로 변환하여 씁니다.

이 코드를 사용하려면

vector<double> val; 

val = GenRandRea(2, 10); 
for (int kk=0; kk<10;kk++){ 
    cout << setprecision(9) << val[kk] << endl; 
} 

예를 들어, 생산에 대한 어떤 의지 :

0.767902586 0.848146121 0.727780818 0.408328773 0.88750684 0.83126026 0.253109609 0.620335586 0.569496621 0.145755069

감사합니다!