C++의 난수 생성에는 약간의 제한이 있다는 것을 알고 있습니다 (비 균일 할 수 있음). 1에서 14620까지의 숫자를 생성하려면 어떻게해야합니까?난수 생성기, C++
감사합니다.
C++의 난수 생성에는 약간의 제한이 있다는 것을 알고 있습니다 (비 균일 할 수 있음). 1에서 14620까지의 숫자를 생성하려면 어떻게해야합니까?난수 생성기, C++
감사합니다.
일반적인 방법은 모듈로 std::rand()
을 사용하는 것이다 @tenfour 그의 대답 언급로
#include<cstdlib>
#include<ctime>
// ...
std::srand(std::time(0)); // needed once per program run
int r = std::rand() % 14620 + 1;
그러나, 모듈러스 연산자 값 std::rand()
복귀의 균일 성을 방해 할 수있다. 이것은 모듈러스가 버려지는 값을 유효한 값으로 변환하기 때문이며,이 변환은 일정하지 않을 수 있습니다. 예를 들어, [0, 10]의 n
의 경우 값 n % 9
은 9를 0으로 변환하므로 true 0 또는 9로 0을 얻을 수 있습니다. 다른 값은 각각 한 번만 얻을 수 있습니다.
대체 접근법은 std::rand()
의 난수를 [0, 1] 범위의 부동 소수점 값으로 변환 한 다음 원하는 범위 내로 값을 변환하고 이동하는 것입니다.
int r = static_cast<double>(std::rand())/RAND_MAX * 14620 + 1;
rand을 사용하십시오.
(rand() % 100) is in the range 0 to 99
(rand() % 100 + 1) is in the range 1 to 100
(rand() % 30 + 1985) is in the range 1985 to 2014
(rand() % 14620 + 1) is in the range 1 to 14620
EDIT은 :
링크에서 언급했듯이, 랜더 마이저를 사용 전에 srand
시드를 사용한다. 사용할 공통적 인 가치는 time
으로 전화 한 결과입니다. 다른 사람이 대답대로
중요한 추가 정보는 빠졌습니다. *이 모듈러스 연산은 스팬에 진정으로 균일하게 분포 된 난수를 생성하지 않습니다. * – meagar
시드를 사용하지 않고 오른쪽. 링크는 페이지 하단에 시드를 언급합니다. 이것을 포함하도록 업데이트하겠습니다. – James
@James, @meagar, 어떻게하면 균일하게 분산 된 난수를 생성 할 수 있을까요? 알고리즘의 한 루프 내에서 30,000 개를 생성해야합니다. – notrockstar
고맙습니다. 이제 막 부스트 라이브러리를 배우기 시작했습니다. – notrockstar
srand()/rand()
는 당신이 필요로하는 기능이다 부스트 라이브러리를 사용하여 튜토리얼입니다.
%
의 문제점은 결과가 분명히 균일하지 않다는 것입니다. 예를 들어, rand()
이 0-3의 범위를 반환한다고 상상해보십시오.
0 - 2000 times
1 - 1000 times
2 - 1000 times
아야 : 당신이 (rand() % 3)
에 대해 동일한 샘플링을 할 경우
0 - 1000 times
1 - 1000 times
2 - 1000 times
3 - 1000 times
지금, 당신은 결과가 같을 것이라고주의 사항 : 여기에 가상 그것을 4000 번 호출의 결과는! 더 균일 한 해결책은 이것이다 : 정치 못한 코드에 대한
int n = (int)(((((double)std::rand())/RAND_MAX) * 14620) + 1);
미안하지만, 아이디어는 부동 소수점 연산을 사용하여 원하는 범위를 적절하게 축소하고, 정수로 변환하는 것입니다. 당신이 C + +0 환경, 부스트 LIB의 가까운 유도체를 가지고있는 경우에
: +1 좋은 지적입니다. – wilhelmtell
'(((double) std :: rand())/RAND_MAX)'-이 부분에 대해 설명해 주시겠습니까? 난수를 생성 한 다음 RAND_MAX로 스케일을 조정합니까? – notrockstar
을'RAND_MAX'로 나눔으로써 0.0에서 1.0 사이의 균일 한 난수를 생성합니다. 따라서 원하는 범위로 쉽게 확장 할 수 있습니다. 너의 경우, 1-14620. – tenfour
이제 표준 :
는#include <random>
#include <iostream>
int main()
{
std::uniform_int_distribution<> d(1, 14620);
std::mt19937 gen;
std::cout << d(gen) << '\n';
}
이 빠르고, 쉽고 높은 품질 될 것입니다.
는당신은 지정하지만, 대신 부동 소수점 원한다면 그냥 하위하지 않았다 :
std::uniform_real_distribution<> d(1, 14620);
그리고 당신은 비 균일 한 분포를 필요한 경우, 당신은 당신의 자신의 작품이 많다는 상수 또는 piece-을 구축 할 수 있습니다 현명한 선형 분포가 매우 쉽습니다.
균일 한 int 분포와 uniform real 분포 사이에는 중요한 차이가 있음에 유의하십시오. 균일 한 int 분포는 '닫힌 범위'[1,14620]의 숫자를 반환하고 균일 한 실제 분포는 '반 개방 범위'의 숫자를 반환합니다 [1,14620]. – Blastfurnace
C++ 0x-esque 시드도 사용할 수 있습니다.'std :: random_device r; std :: mt19937 gen (r());' – Cubbi
그리고 C++ 0x가 없다면 boost :: random은 아마도 당신이 정말로 빠르고 더러운 것을 필요로하지 않는다면 아마 표준이 될 것입니다 ... – Chinasaur
이미 말한 것처럼 rand()을 사용할 수 있습니다. 예 :
int n = rand() % 14620 + 1;
rand()
이 0에서
RAND_MAX
범위의 값을 산출하고
RAND_MAX
이 일반적으로 14620으로 나눌 수 없기 때문입니다.
RAND_MAX == 15000
일 경우
rand() == 0
및
rand() == 14620
이 모두
n==1
이지만
rand()==999
만 출력하면
n==1000
이되므로 숫자 1은 숫자 1000의 두 배가됩니다.
그러나 14620이 RAND_MAX
보다 훨씬 작 으면이 효과는 무시할 수 있습니다. 내 컴퓨터에서 RAND_MAX
은 2147483647과 같습니다. rand()
은 2147483647 % 14620 = 10327 및 2147483647/14620 = 146886이므로 균등 한 샘플을 0에서 RAND_MAX로 산출하면 n
은 평균 146887 번, 1에서 10328 사이이며 10329와 2147483647 샘플을 그릴 경우 14620이 평균 146886 번 발생합니다. 나 한테 큰 차이가 없다.
그러나 RAND_MAX == 15000
인 경우 위의 설명과 같이 변경됩니다. 이 경우 일부 이전 게시물
int n = (int)(((((double)std::rand())/RAND_MAX) * 14620) + 1);
가 '더 균일'하기 위해 사용하는 제안했다. rand()
은 여전히 유일한 값 RAND_MAX
의 고유 값을 반환하므로 더 자주 발생하는 숫자 만 변경됩니다. 정말 균일하게 만들려면 정수형 rand()
이 14620 * int (RAND_MAX/14620)와 RAND_MAX 사이의 범위에 있고 rand()
을 다시 호출해야합니다. RAND_MAX == 15000
의 예제에서는 rand()
의 값을 14620과 15000 사이에서 거부하고 다시 그립니다. 대부분의 응용 프로그램에서는 이것이 필요하지 않습니다. 난 rand()
의 임의성에 대해 더 걱정할 것입니다.
계수 운영자가 가장 중요하다,이 계수에 제한을 적용 할 수 있습니다,이 체크 아웃 :
// random numbers generation in C++ using builtin functions
#include <iostream>
using namespace std;
#include <iomanip>
using std::setw;
#include <cstdlib> // contains function prototype for rand
int main()
{
// loop 20 times
for (int counter = 1; counter <= 20; counter++) {
// pick random number from 1 to 6 and output it
cout << setw(10) << (1 + rand() % 6);
// if counter divisible by 5, begin new line of output
if (counter % 5 == 0)
cout << endl;
}
return 0; // indicates successful termination
} // end main
랜드를() 함수는 정말 최고의 랜덤 생성기 아니라, 더 좋은 방법이 될 것이다 CryptGenRandom()을 사용하여.
#include <Windows.h>
// Random-Generator
HCRYPTPROV hProv;
INT Random() {
if (hProv == NULL) {
if (!CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, CRYPT_SILENT | CRYPT_VERIFYCONTEXT))
ExitProcess(EXIT_FAILURE);
}
int out;
CryptGenRandom(hProv, sizeof(out), (BYTE *)(&out));
return out & 0x7fffffff;
}
int main() {
int ri = Random() % 14620 + 1;
}
지금 심지어 C++에서 임의의 숫자를 사용하는 방법을 찾아 볼나요 :
이 예는 트릭을 할해야합니까? 또한 C++에서 임의의 숫자로 작성된 더 나은 솔루션이 필요하거나 단순히 rand 사용 방법에 대해 설명하는 경우를 언급하지 않았습니다. – thecoshman
C++에 고유 한 "난수 생성 제한 사항"이 무엇을 의미하는지 명확히 할 수 있습니까? 다소 균일 한 시퀀스는 더 좋거나 적은 발전기에서 발생합니다. – Francesco
rand()가 (균일하지 않을 수 있다면)별로 유용하지 않을 것입니다. –