'가중치'에 해당되는 글 1건

  1. 2018.03.13 가중치 랜덤 생성
프로그래밍/C#2018. 3. 13. 21:21

1부터 n까지의 중에서 랜덤 값을 고르는 것은 쉽다

그냥 제공해주는 랜덤 함수를 사용하면 된다. (유니티의 경우는 Random.Range(1,n+1) 이정도.)

그런데 가중치를 적용해서 랜덤 숫자를 뽑는 것은 조금의 작업을 해줘야 한다.

예를 들어 1~5까지의 수가 있는데

1 가중치는 10

2 가중치는 20

3 가중치는 30

4 가중치는 40

5 가중치는 50

이런 식으로 가중치가 있을 수가 있다.

값들을 동일선상에 위치 시키고, 그 선상에 랜덤 피봇이 어디에 있는지를 확인한다는 원리를 활용하면 

가중치가 적용된 확률을 뽑을 수 있다.

게임 내에서 아이템들마다 생성 확률이 다를 사용 있겠다.

예전엔 다소 무식한 방법으로 처리를 했었는데.. 

이번에 면접을 보면서 문제로 나와서 다시 한번 작성 해봤다.


(Main함수는 확인용 코드고, GetRandom에 작성 했다. 두번째 인자인 seed값은 너무빨리 랜덤클래스를 만들면 난수가 제대로 생성되지 않는 문제를 해결하기 위해 넣었다. 짧은시간에 엄청난 양의 처리를 하지 않는다면 필요 없다.)



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
   class Program
    {
        static float GetRandom(float[] inputDatas, int seed)
        {
 
            Random random = new Random(seed);
 
            float total = 0;
 
            for (int i = 0; i < inputDatas.Length; i++)
            {
                total += inputDatas[i];
            }
 
            float pivot = (float)random.NextDouble() * total;
 
            for (int i = 0; i < inputDatas.Length; i++)
            {
                if (pivot < inputDatas[i])
                {
                    return inputDatas[i];
                }
                else
                {
                    pivot -= inputDatas[i];
                }
            }
            return inputDatas[inputDatas.Length - 1];
        }
 
        static void Main(string[] args)
        {
            Dictionary<floatint> datas = new Dictionary<floatint>();
 
            float[] probs = new float[] { 10f,20f,30f,40f,50f};
 
            int tryNum = 500000
 
            Random seedRnd = new Random();
            int startIndex = seedRnd.Next();
 
            for (int i = startIndex; i < startIndex+ tryNum; i++)
            {
                float returnValue = GetRandom(probs,i);
                if (datas.ContainsKey(returnValue) == false)
                {
                    datas.Add(returnValue, 1);
                }
                else
                {
                    datas[returnValue] ++;
                }
            }
 
            Console.WriteLine(string.Format("시행 횟수 : {0}",tryNum));
 
            List<float> keys = datas.Keys.ToList();
            keys.Sort();
 
            for(int i = 0; i < keys.Count; i++)
            {
                Console.WriteLine(string.Format("{0}이 {1}번 나옴 비율 : {2}%", keys[i], datas[keys[i]], ((float)datas[keys[i]] / (float)tryNum) * 100f));
            }                   
 
        }
     
 
    }
cs

결과

숫자마다 정확한 값이 나오지 않은 이유는 총 합이 100%를 넘기기 때문이다.

총 합이 100%라면 거의 근사한 값이 나올 것이다.

'프로그래밍 > C#' 카테고리의 다른 글

using , Dispose()  (0) 2018.03.21
퀵소트  (0) 2018.03.15
이진탐색  (0) 2018.03.11
c# string으로 class 인스턴스 생성하기  (0) 2017.09.04
c# ref , out 키워드의 차이  (0) 2016.12.30
Posted by JinFluenza