C / C ++로 작성된 작은 응용 프로그램에서 rand
함수와 시드에 문제가 있습니다 .
다른 순서, 즉 다른 로그 값 (베이스 2)의 난수 시퀀스를 생성하고 싶습니다. 그러나 생성 된 모든 숫자는 동일한 순서이며 2 ^ 25와 2 ^ 30 사이에서 변동합니다.
rand()
지금은 비교적 큰 숫자 인 유닉스 타임이 뿌려 졌기 때문 입니까? 내가 무엇을 잊고 있습니까? 나는 rand()
시작 부분에 한 번만 시드 합니다 main()
.
답변
1과 2 사이의 숫자의 3 %가있다 (30) NOT 2 사이 (25) , 2 (30) . 그래서, 이것은 꽤 정상적인 소리입니다 🙂
이 때문에, 25 / 2 30 = 2 -5 = 1/32 = 0.03125 = 3.125 %
답변
연한 녹색은 0과 2 25 사이의 영역입니다 . 짙은 녹색은 2 25 와 2 30 사이의 영역 입니다. 진드기는 2의 거듭 제곱입니다.
답변
더 정확해야합니다 : 다른 기본 2 로그 값을 원하지만 어떤 분포 를 원하십니까? 표준 rand () 함수는 균일 분포를 생성하므로 원하는 분포와 연관된 Quantile 함수를 사용하여이 출력을 변환해야합니다 .
배포판을 알려 주면 필요한 quantile
기능을 알려줄 수 있습니다 .
답변
다른 크기의 순서를 원한다면 단순히 시도해보십시오 pow(2, rand())
. 아니면 Harold가 제안한 것처럼 rand ()로 직접 주문을 선택합니까?
답변
@ C4stor가 좋은 지적을했습니다. 그러나 더 일반적인 경우와 인간 (베이스 10)에 대해 이해하기 쉽도록 1 ~ 10 ^ n 범위에서 숫자의 ~ 90 %는 10 ^ (n-1) ~ 10 ^ n입니다. 숫자의 ~ 99 %가 10 ^ (n-2)에서 10 ^ n으로 이동합니다. 원하는만큼 소수점을 계속 추가하십시오.
재미있는 수학, n을 위해 이것을 계속하면,이 방법으로 1에서 10 ^ n, 99.9999 … % = 100 % 의 숫자가 10 ^ 0에서 10 ^ n 사이임을 알 수 있습니다.
이제 코드에 대해 0에서 10 ^ n 사이의 임의의 크기의 난수를 원한다면 다음을 수행 할 수 있습니다.
-
0에서 n까지 작은 난수 생성
-
n의 범위를 알고 있다면 k> max {n} 인 10 ^ k의 큰 난수를 생성하십시오.
-
이 큰 난수의 n 자리를 얻으려면 더 긴 난수를 자릅니다.
답변
기본 (정확한) 대답은 이미 위에서 주어졌고 수락되었습니다 .0과 9 사이의 10 숫자, 10과 99 사이의 90 숫자, 100과 999 사이의 900 등이 있습니다.
대략 로그 분포를 갖는 분포를 계산하는 효율적인 방법을 위해 임의의 숫자를 임의의 숫자로 오른쪽으로 이동하려고합니다.
s = rand() & 31; // a random number between 0 and 31 inclusive, assuming RAND_MAX = 2^32-1
r = rand() >> s; // right shift
완벽하지는 않지만 컴퓨팅보다 훨씬 빠릅니다 pow(2, rand()*scalefactor)
. 분포는 요소 2 (128에서 255에 대해 균일하고 256에서 1023에 대한 밀도의 절반 등) 내의 숫자에 대해 분포가 균일하다는 의미에서 “거칠게”나타납니다.
다음은 숫자 0에서 31까지의 빈도 (1M 샘플)의 히스토그램입니다.
답변
0과 2 ^ 29와 2 ^ 29와 2 ^ 30 사이의 숫자는 정확히 같습니다.
문제를 보는 또 다른 방법 : 생성 한 난수의 이진 표현, 가장 높은 비트가 1 일 확률은 1/2과 같으므로 절반의 경우 29를 얻습니다. 원하는 것은 2 ^ 25 이하의 숫자를 보는 것이지만 5 개의 최상위 비트는 모두 0이며 이는 1/32의 낮은 확률로 발생합니다. 오랫동안 실행하더라도 15 미만의 순서는 전혀 볼 수 없습니다 (확률은 6 6 번 연속으로 굴리는 것과 같습니다).
자, 씨앗에 대한 당신의 질문의 일부. 시드는 숫자가 생성되는 범위를 판별 할 수 없으며 첫 번째 초기 요소 만 결정합니다. rand ()를 범위에서 가능한 모든 숫자의 시퀀스 (사전 결정된 순열)로 생각하십시오. 시드는 시퀀스에서 숫자 그리기 시작 위치를 결정합니다. 그렇기 때문에 (의사) 임의성을 원한다면 현재 시간을 사용하여 시퀀스를 초기화하십시오.
