랜덤연산자 중복관련질문
글쓴이: tkrl2246 / 작성시간: 금, 2017/03/10 - 12:21오전
이 코드에서 중복된 숫자가 랜덤으로 걸리는걸 없애보려고합니다...ㅎㅎ...
어떻게 해야할가요.
그리고 이출력값을 배열에 저장하려면 어떻게 해야할까요?..ㅎㅎ
#include<stdio.h> #include<stdlib.h> #include<Windows.h> int num(int n1, int n2); void main() { srand(GetTickCount()); int i; for (i = 0; i < 10; i++) { printf("%d\n", num(1, 100)); } } int num(int n1, int n2) { return (int)( rand() % 100)+1; }
Forums:
셔플
랜덤의 문제에 있어선 중복을 해결하기 위해서 이미 나온 것이라면 다시 시행하는 방식으로 할 수 있겠지만, 다른 방법으로는 나올 수 있는 모든 경우의 수를 배열 한 뒤 순서를 섞은뒤 하나씩 빼는 방법도 있습니다.
위의 예라면, 100개에 대한 배열을 1, 100까지 증가시켜가면서 채우고, qsort를 수행합니다. 수행할 때 비교하는 함수는
int compare( void * a, void * b )
{
return rand() % 3 - 1;
}
정도로 하면 되지 않을까 싶습니다. 즉 비교를 횡설수설하게해서 섞는 것이지요.
그리고 위의 경우라면 배열의 앞 10개를 출력하면 될 것 같네요.
---
http://coolengineer.com
C언어 라이브러리 rand()로 randomness가
C언어 라이브러리
rand()
에 의존하여 randomness가 정말로 중요한 어플리케이션을 작성하는 것은 불가피하지 않다면 별로 좋은 생각이 아닙니다.일단
(1)randomness 퀄리티 보장이 없고
(2)불편해요.
이웃 동네...라고 하기는 요즘 좀 많이 멀어진 C++ 동네에서는 C++11부터 빵빵하게 지원해 주기 시작한 것과 대조적이죠.
http://en.cppreference.com/w/cpp/numeric/random 참조.
pynoos님의 방식대로 처음부터 다 섞어놓고 시작하는 방식도 있습니다만,
(1) 100개의 숫자 중 10개밖에 안 뽑을 건데 전부 뒤섞을 필요가 있을까요.
뭐 이 문제는 사실 요즘 컴퓨터에서 이 정도 추가 작업은 별로 거슬릴 정도는 아니라고 쳐도...
(2)
qsort()
를 그런 식으로 썼을 때 과연 정말 고르게 뒤섞일지 확신할 수가 없습니다.사실 C++03 정도만 됐어도
random_shuffle
(http://en.cppreference.com/w/cpp/algorithm/random_shuffle)을 쓰면 되는데, C언어에서 그게 제공되지 않는다고 해도qsort()
를 그런 식으로 남용하는 게 정당화되지는 않습니다. 이와 관련된 주제의 질문이 stack overflow에 올라왔었으니 참고 바랍니다.http://stackoverflow.com/questions/790083/does-qsort-demand-consistent-comparisons-or-can-i-use-it-for-shuffling
어쨌거나 질문자님께서 바라는 코드를
rand()
만으로 가장 간편하게 짜기 위해서는 위 링크에서의 여러 답변자들이 제안하는 Fisher–Yates shuffle 알고리즘을 사용하는 게 좋아 보이는군요. 게다가 이 알고리즘은 결과를 앞에서부터 차례차례 생성하도록 구현할 수 있으니 더할 나위 없지요.https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle
구현하는 데 문제가 하나 있다면, 임의 크기의 정수 집합에서 균일한 확률로 정수 하나를 뽑는 함수를 만드는 것이죠. 확률을 정말로 균일하게 만들기가 꽤 까다롭습니다. 아래의
random_range()
와 같이 최대한 노력해 봤습니다만 슬프게도 여전히 완벽하지는 않습니다.(1) 별로 견고한 코드는 아닙니다. 동일한
state
객체를 가지고trial()
을NR_CANDIDATE
회 초과하여 호출하면 무슨 일이 생길지 장담할 수 없다는 말씀입니다.(2) 앞서 말씀드렸듯
random_range()
는 엄밀히 말하면 범위 안의 정수를 균일한 확률로 생성하지 못합니다. 미세한 확률 차이가 생기는데, 왜 그런지는 직접 생각해 보세요. 어쨌든 저는 최선을 다했습니다. 사실 어차피 미묘한 차이라 그냥 naive한 구현을 쓰는 사람도 많아요.(3) 질문자님이 출력을 배열에 저장하는 방법도 질문하시길래
main()
에서 배열에 한 번 담았다가 출력시켰습니다.(4) 저는 지금 윈도우즈에서 사용 가능한 컴파일러가 없기 때문에
#include <Windows.h>
및srand(GetTickCount());
부분은 리눅스에서 컴파일 가능한 코드로 대체하여 작성하고 테스트했습니다. 그러니 그 부분에서 컴파일 문제가 생기더라도 양해해 주시길.(5) randomness가 들어가는 프로그래밍은 까다로워요. 다른 고수 분들의 답변도 기대하겠습니다.
각각 범위를 지정해보시면. 편할겁니다.
범위'를 지정하면. 중복이 안되죠. ㅇ_ㅇ''
대충 만드느라. 코드가 정확하지는 않을 수 있습니다.
----------------------------------------------------------------------------
젊음'은 모든것을 가능하게 만든다.
매일 1억명이 사용하는 프로그램을 함께 만들어보고 싶습니다.
정규 근로 시간을 지키는. 야근 없는 회사와 거래합니다.
각 분야별. 좋은 책'이나 사이트' 블로그' 링크 소개 받습니다. shintx@naver.com
댓글 달기