뽑은 수를 보관했다가 중복 체크를 하는것이 효율적인지,
전체 수를 가지고 있다가 뽑은 수를 제거하는것이 효율적인지 잘 모르겠네요.
if로 일일이 비교 하는 것 보다, memcpy가 더 빠를 것 같기도하고...
(vector에서 중간값을 제거했을 때 memcpy가 일어난다는 가정입니다. memcpy 맞겠죠?)
어쨋든... 후자를 선택하고 만들었습니다.
class TNoDuplRand {
std::vector Num;
public:
__fastcall TNoDuplRand(int Size)
{
Num=std::vector(Size);
for (int i = 0; i < Size; i++) {
Num[i]=i;
}
}
int __fastcall GetRandomNum(void)
{
if ((int)Num.size()) {
randomize();
int idx=random(Num.size());
int retval=Num[idx];
Num.erase(Num.begin()+idx);
return retval;
}else {
return -1;
}
}
__fastcall ~TNoDuplRand()
{
Num.~vector();
}
};
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
int Count=10;
TNoDuplRand *a = new TNoDuplRand(Count);
for (int i = 0; i < Count+1; i++) {
Memo1->Lines->Add(a->GetRandomNum());
}
}
대학생 님이 쓰신 글 :
: 난수 중복 없애는 것은 프로그램과 소스코드에 따라서
:
: 방법이 다 천차만별이긴한데 그래도 작성하고 있는
:
: 프로그램에 난수중복을 없애려고 하면 항상 머리 아픈것은
:
: 사실입니다..ㅡㅡ;;;;; 난수중복 없애는 거 이거
:
: 뭔가 알고리즘이나 수학적으로 정해져있는 방법 같은거 있나요??
:
: 알고리즘과 수학이 존재하는 이유가 이럴때 문제를 해결하라고
:
: 존재하는 것이 맞기는 한데 2000페이지가 넘어가는 알고리즘 도서나
:
: 관련내용의 수학도서 여러권을 찾아봐도 그런얘기가 잘 없더라구요...ㅠㅠ
|
// 하지만 현실적으로 나중으로 갈수록 빈곳을 뽑을 확률일 줄어들어
// 실용상 사용하기 힘들다. Max 1000 넘어가면
// 1초 이상 걸려서 사용하기 힘듦.
class CNoDuplRand2
{
public:
vector<int> Num;
int Max;
public:
CNoDuplRand2(int max)
{
Max = max;
}
int GetRandomNum(void)
{
if ((int)Num.size() >= Max) // 지정 범위내에서 새로운 난수는 더이상 없음.
return -1;
bool find;
int num;
int loop = 0;
randomize();
do
{
find = false;
num = random(Max);
for(int c = 0; c < (int)Num.size(); c++)
if (Num[c] == num)
{
find = true;
break;
}
loop++;
if (loop > Max * Max * 2)
return -2;
} while(find);
Num.push_back(num);
return num;
}
};