출처:https://skyfe.tistory.com/entry/%ED%99%95%EB%A5%A0%EC%9D%84-%EC%A0%81%EC%9A%A9%ED%95%9C-%EB%9E%9C%EB%8D%A4%EA%B0%92-%EC%84%A0%ED%83%9D%ED%95%98%EA%B8%B0

 

#include "pch.h"
#include <iostream>
#include <time.h>
#include <map>
#include <functional>
#include <random>

/*
  값에 따라 원하는 확률로 선택되도록 하기

  아래의 확률로 선택하고 싶은 경우
  값 확률
  0 35%
  1 30%
  2 15%
  3 15%
  4 5%

  누적확률 사용하면 가능하며 낮은 확률부터 정렬해야 함
  값 확률 누적확률값
  4 5% 5%
  3 15% 20%
  2 15% 35%
  1 30% 65%
  0 35% 100%
*/


/*
  rand() 사용
  프로그램 시작시 srand(time(NULL)) 을 하여
  매번 다른 rand() 값이 나오도록 한다. (seed)
*/
int get_rand1()
{
  int random = rand();

  double r = random / (double)RAND_MAX; // 0.0 ~ 1.0
  double dr = r * 100.0f; // 0.0 ~ 100.0


  double p[] = { 5.0f, 15.0f, 15.0f, 30.0f, 35.0f }; //4, 3, 2, 1, 0

  double cumulative = 0.0f;

  for (int i = 0; i < 5; i++) {
  cumulative += p[i];
  if (dr <= cumulative) {
  return 4 - i;
  }
  }
  return -1;
}


/*
  c+11 random_device 사용
*/
int get_rand2()
{
  static std::uniform_int_distribution<int> range(0, 100);
  static std::random_device rn;
  static std::mt19937_64 rnd(rn());

  double dr = static_cast<double>(range(rnd));

  double p[] = { 5.0f, 15.0f, 15.0f, 30.0f, 35.0f }; //4, 3, 2, 1, 0

  double cumulative = 0.0f;

  for (int i = 0; i < 5; i++) {
  cumulative += p[i];
  if (dr <= cumulative) {
  return 4 - i;
  }
  }
  return -1;
}


void test_rand(int count, std::function<int(void)> random_func)
{
  std::map<int, int> map;

  // 결과 저장
  for (int i = 0; i < count; ++i) {
  int ret = random_func();

  auto it = map.find(ret);
  if (it == map.end()) {
  map.emplace(ret, 1);
  }
  else {
  it->second = it->second++;
  }
  }
  std::cout << std::endl;

  // 결과 출력
  for (auto it : map) {
  double percent = (it.second * 100) / (double)count;
  std::cout << it.first << " - " << percent << "% (" << it.second << ")" << std::endl;
  }
}


int main()
{
  int count = 100000;
  test_rand(count, std::function<int(void)>(get_rand1));
  test_rand(count, std::function<int(void)>(get_rand2));

  return 0;
}

 

실행 결과 :

 

0 - 35.047% (35047)

1 - 30.266% (30266)

2 - 14.71% (14710)

3 - 15.001% (15001)

4 - 4.976% (4976)

 

0 - 34.611% (34611)

1 - 29.652% (29652)

2 - 15.13% (15130)

3 - 14.732% (14732)

4 - 5.875% (5875)