c++ 함수를 확률로 발생할수 있나요?

예를 들어

A(), B(), C() 함수가 이렇게 있는데

A() 함수는 10%확률로 발생 B() 삼수는 20%, C() 30%로 발생 .

이렇게 짜는 방법이 있을까요?

3답변

  • 난수 함수등을 이용해 확률적으로 특정 값을 리턴하는 알고리즘을 만든 다음
    해당 값을 보고 어떤 함수를 호출할지 결정하는 식으로 코드를 짜면 되겠지요.

    아래는 그냥 예를 들기 위해 간단하게 작성해본 것으로 더 좋은 방법들이 많을 겁니다. random 함수도 진짜로 랜덤하게 값을 뱉는게 아니다 보니 좀더 정확한 확률을 계산하기 위해서는 여러가지 아이디어를 더 추가해야 할 것입니다.

    int ary[10] = {1, 2, 2, 3, 3, 3, 0, 0, 0, 0};
    int index = 0;
    int nfunc = 0;
    
    index = random() % 10;       // 0~9 까지 값을 랜덤하게 구함
    nfunc = ary[index];          // 랜덤하게 구한 값으로 배열의 값을 가져옴
    
    if (nfunc == 1)  A();
    else if (nfunc == 2) B();
    else if (nfunc == 3) C();
    
  • 난수함수를 구현하는 일은 매우 어렵습니다. 그래서 c++ 에서는<cstdlib>에서 난수함수가 구현되어 있습니다.

    
    #include <iostream>
    #include <cstdlib>
    using namespace std;
    
    int main(){
        for(int i=0; i<10; i++)
            cout<<rand()<<endl;
    }
    
    

    하지만 이 코드를 실행시키면 항상 같은 값들이 순서대로 나오는 것을 알 수가 있는데 그 이유는 바로 seed 입니다. 난수함수의 seed를 지정해주어야 하는데 이를 지정해주지 않아서 항상 기본값으로 됩니다. 그래서 프로그래머들은 다음과 같은 코드를 사용합니다.

    
    #include <iostream>
    #include <cstdlib>
    #include <ctime>
    using namespace std;
    
    int main(){
        srand(time(0));
        for(int i=0; i<10; i++)
            cout<<rand()<<endl;
    }
    
    

    바로 시간함수를 seed로 사용하는 것입니다. 시간은 항상 바뀌기 때문에 항상 다른 난수를 얻어낼수 있습니다.

    이제 이를 응용하면 다음과 같이 됩니다.

    
    #include <bits/stdc++.h>
    using namespace std;
    
    void A(){
        if(rand()%10>0)
            return;
        //code
    }
    
    void B(){
        if(rand()%10>1)
            return;
        //code
    }
    
    void C(){
        if(rand()%10>2)
            return;
        //code
    }
    
    int main(){
        srand(time(0));
        //code
    }
    
    
  • 함수의 인자와 반환값이 같다면, 함수 포인터를 사용하여 재밌는 작업을 수행하실 수 있을겁니다.

    void A() { cout << "A" << endl; }
    void B() { cout << "B" << endl; }
    void C() { cout << "C" << endl; }
    void E() {} // do nothing
    

    라고 가정하고 다음과 같은 코드를 작성할 수 있습니다. 이 때, 꼭 A의 반환 값이 void일 리는 없기 때문에 다음과 같이 해봅시다.

    // decltype(A)   : A 함수의 타입을 추론하여 그 타입을 사용
    // decltype(A) * : A 함수의 함수 포인터
    decltype(A) * arr[10] {  A, B, B, C, C, C, E, E, E, E };
    

    난수는 무엇을 사용해도 상관없고, 직접 arr을 섞어도 괜찮습니다. 이 답변의 예제에서는 표준 라이브러리 #include <random>을 사용해 보겠습니다.

    #include <iostream>
    #include <random>
    
    using namespace std;
    
    void A() { cout << "A" << endl; }
    void B() { cout << "B" << endl; }
    void C() { cout << "C" << endl; }
    void E() {} // do nothing
    
    int main()
    {
        // decltype(A)   : A 함수의 타입을 추론하여 그 타입을 사용
        // decltype(A) * : A 함수의 함수 포인터
        decltype(A) * arr[10] {  A, B, B, C, C, C, E, E, E, E };
    
        random_device dre;
        uniform_int_distribution<> ui{ 0, 9 };
    
        // random index
        auto random_index = ui(dre);
    
        // call func
        arr[random_index]();
    }
    

ᕕ( ᐛ )ᕗ
로그인이 필요합니다

작성한 답변에 다른 개발자들이 댓글을 작성하거나 댓글에 좋아요/싫어요를 할 수 있기 때문에 계정을 필요로 합니다.