에 관한 rand() % n
이상적이지 인
이렇게는 rand() % n
비 균일 한 분포를 가지고있다. 값의 수가 20의 배수가 아니기 때문에 특정 값의 불균형 한 수를 얻습니다.
다음 rand()
으로 일반적으로 선형 합동 발생기입니다 ( 다른 것들도 많지만 , 이것이 가장 구현 가능성이 높으며 이상적인 매개 변수보다 적습니다 (매개 변수를 선택하는 방법이 많이 있습니다). 이것의 가장 큰 문제는 종종 낮은 비트 ( % 20
유형 표현을 가진 비트 )가 무작위가 아니라는 것입니다. 나는 일을 기억 rand()
에서 번갈아 가장 낮은 비트 곳 년 전 1
으로 0
각 호출로는 rand()
매우 무작위 아니었다 -.
에서 랜드 (3) 매뉴얼 페이지 :
Linux C 라이브러리의 rand () 및 srand () 버전은 동일합니다.
random () 및 srandom ()과 같은 난수 생성기이므로 하위
비트는 상위 비트와 동일해야합니다. 그러나 더 오래된
rand () 구현 및 다른 구현에 대한 현재 구현
시스템에서 하위 비트는 상위 비트보다 훨씬 덜 무작위입니다.
주문 비트. 이 기능을 응용 프로그램에서 사용하지 마십시오
좋은 무작위성이 필요할 때 휴대용.
이것은 이제 히스토리로 강등 될 수 있지만 여전히 스택의 어딘가에 숨어있는 rand () 구현이 좋지 않을 수 있습니다. 이 경우에도 여전히 적용 가능합니다.
할 일은 실제로 좋은 난수 라이브러리 (좋은 난수를 제공하는)를 사용하고 원하는 범위 내의 난수를 요구하는 것입니다.
좋은 임의의 숫자 비트 코드 예 (링크 된 비디오에서 13:00부터)
#include <iostream>
#include <random>
int main() {
std::mt19937 mt(1729); // yes, this is a fixed seed
std::uniform_int_distribution<int> dist(0, 99);
for (int i = 0; i < 10000; i++) {
std::cout << dist(mt) << " ";
}
std::cout << std::endl;
}
이것을 다음과 비교하십시오.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main() {
srand(time(NULL));
for (int i = 0; i < 10000; i++) {
printf("%d ", rand() % 100);
}
printf("\n");
}
이 두 프로그램을 모두 실행하고 해당 출력에서 특정 숫자가 얼마나 자주 나타나는지 비교하십시오.
관련 비디오 : rand ()는 유해한 것으로 간주
rand ()의 일부 역사적 측면은 Nethack에서 버그를 발생시키는 것으로 자체 구현에서보고 고려해야합니다.
Nethack RNG 문제
Rand ()는 Nethack의 난수 생성을위한 매우 기본적인 함수입니다. Nethack이 그것을 사용하는 방식은 버그가 있거나 lrand48 ()은 거친 의사 난수를 생성한다고 주장 할 수 있습니다. 그러나 lrand48 ()은 정의 된 PRNG 메소드를 사용하는 라이브러리 함수이며이를 사용하는 모든 프로그램은 해당 메소드의 약점을 고려해야합니다.
버그는 Nethack이 lrand48 ()의 결과의 하위 비트에 의존하는 경우가 있습니다 (때로는 rn (2)의 경우와 동일). 이로 인해 전체 게임에서 RNG가 제대로 작동하지 않습니다. 이는 특히 사용자 행동이 캐릭터 생성 및 1 차 레벨 생성과 같은 추가 임의성을 도입하기 전에 주목할 만합니다.
위의 2003 년부터는 의도 한 게임을 실행하는 모든 시스템이 좋은 rand () 함수를 가진 최신 Linux 시스템 일 경우가 아니라는 점을 명심해야합니다.
이 작업을 직접 수행하는 경우 코드 를 작성 하고 ent로 출력을 테스트 하여 난수 생성기가 얼마나 좋은지 테스트 할 수 있습니다 .
난수의 속성에
정확히 무작위가 아닌 '무작위'에 대한 다른 해석이 있습니다. 임의의 데이터 스트림에서 동일한 수를 두 번 얻을 수 있습니다. 동전을 뒤집 으면 (무작위), 두 개의 머리를 연속적으로 얻을 수 있습니다. 또는 주사위를 두 번 던지고 같은 숫자를 두 번 연속으로 얻습니다. 또는 룰렛을 돌리고 같은 숫자를 두 번 얻습니다.
숫자의 분포
노래 목록을 재생할 때 '무작위'는 동일한 노래 나 아티스트가 연속해서 두 번 재생되지 않을 것을 의미합니다. 재생 목록이 간주됩니다 두 번 연속 비틀즈 플레이 데 (그것이 비록 '임의하지' 입니다 임의). 네 곡의 재생 목록에 대해 총 여덟 번 재생되었다는 인식 :
1 3 2 4 1 2 4 3
다음보다 '무작위'입니다.
1 3 3 2 1 4 4 2
노래의 '셔플 링'에 대한 자세한 내용 : 노래 를 섞는 방법?
반복되는 값
값을 반복하지 않으려면 고려해야 할 다른 접근 방법이 있습니다. 가능한 모든 값을 생성하고 섞으십시오.
전화 rand()
(또는 다른 난수 생성기)를 호출하는 경우 교체를 호출합니다. 항상 같은 숫자를 두 번 얻을 수 있습니다. 한 가지 옵션은 요구 사항에 맞는 값을 선택할 때까지 계속해서 값을 던져 넣는 것입니다. 나는 이것이 비 결정적 런타임을 가지고 있으며 더 복잡한 역 추적을 시작하지 않으면 무한 루프가있는 상황에서 자신을 찾을 수 있다고 지적합니다.
리스트와 픽
또 다른 옵션은 가능한 모든 유효한 상태 목록을 생성 한 다음 해당 목록에서 임의의 요소를 선택하는 것입니다. 방에있는 빈 곳 (일부 규칙에 맞는)을 모두 찾은 다음 해당 목록에서 임의의 지점을 선택하십시오. 그런 다음 끝날 때까지 반복해서 수행하십시오.
혼합
다른 방법은 마치 카드 한 벌처럼 셔플하는 것입니다. 으로 시작 하는 모든 방에 빈 반점 후 빈 공간을 요청하는 각 규칙 / 프로세스에 한 번에 빈 반점, 하나를 처리하여 그들을 할당 시작합니다. 카드가 부족하거나 카드 요청이 중단되면 완료됩니다.