C / C ++ rand()函数用于偏向期望

时间:2018-03-06 04:50:15

标签: random probability

我使用<stdlib.h> rand()函数在范围[0 ... 9]内生成100个随机整数。我使用以下方法在相等分布上生成它们,

int random_numbers[100];
for(register int i = 0; i < 100; i++){
    random_numbers[i] = rand() % 10;
}

这很好用。但是现在我希望获得100个数字,我希望这些数字的50%左右是5.我该怎么做?

扩展问题

我想得到100个号码。如果我想要这些数字的50%将在0~2之间怎么办?我的意思是这些数字的50%只包含数字0,1,2。怎么做?

我期待可以在10或100的边界之外应用的通用步骤。

5 个答案:

答案 0 :(得分:2)

嗯,如何选择017之间的随机数,如果数字大于9,请将其更改为5

对于0 - 17,你会得到像

这样的发行版
0,1,2,3,4,5,6,7,8,9,5,5,5,5,5,5,5,5

代码:

int random_numbers[100];
for(register int i = 0; i < 100; i++){
    random_numbers[i] = rand() % 18;
    if (random_numbers[i] > 9) {
        random_numbers[i] = 5;
    }
}

您基本上添加了一组超出所需范围的数字,当翻译为5时,会为您提供相同数量的5non-5

答案 1 :(得分:2)

为了让 这些数字的50%在[0, 2]范围内,您可以将rand()的整个范围分成两个相等的一半,然后使用相同的基于%的技术将上半部分映射到[0, 2]范围,将后半部分映射到[3, 9]范围。

int random_numbers[100];
for(int i = 0; i < 100; i++)
{
  int r = rand();
  random_numbers[i] = r <= RAND_MAX / 2 ? r % 3 : r % 7 + 3;
}

要获得 这些数字中的50%为5,类似的技术将起作用。只需将后半部分映射到[0, 9]范围并排除5

int random_numbers[100];
for(int i = 0; i < 100; i++)
{
  int r = rand();

  if (r <= RAND_MAX / 2)
    r = 5;
  else if ((r %= 9) >= 5)
    ++r;

  random_numbers[i] = r;
}

答案 2 :(得分:1)

我认为使用其他答案中提到的技术很容易解决50%的特定问题。让我们试着回答一般情况下的问题 - 我们假设您想要一个分布,您希望数字{A1, A2, .. An}的百分比{P1, P2, .. Pn}Pi的总和是100%(并且所有百分比都是整数,如果不是可以调整)。

我们将创建一个100大小的数组,并用数字A1-An填充它。

int distribution[100];

现在我们填写每个数字,它是百分比的次数。

int postion = 0;
for (int i = 0; i < n; i++) {
    for( int j = 0; j < P[i]; j++) {
        // Add a check here to make sure the sum hasn't crossed 100
        distribution[position] = A[i];
        position ++;
    }
}

现在初始化完成一次,您可以将随机数绘制为 -

int number = distribution[rand() % 100];

如果您的百分比不是整数但是您希望精确度为0.1%,则可以创建一个1000而不是100的数组。

答案 3 :(得分:1)

在这两种情况下,目标是从一组中选择50%,从另一组中选择50%。代码可以调用rand()并使用一些位(一个)来选择组,剩余的位用于值选择。

如果所需的数字范围远小于RAND_MAX,则首次尝试可以使用:

int rand_special_50percent(int n, int special) {
  int r = rand();
  int r_div_2 = r/2;
  if (r%2) {
    return special;
  }
  int y = r_div_2%(n-1);  // 9 numbers left 
  if (y >= special) y++;
  return y;
}

int rand_low_50percent(int n, int low_special) {
  int r = rand();
  int r_div_2 = r/2;
  if (r%2) {
    return r_div_2%(low_special+1);
  }
  return r_div_2%(n - low_special) + low_special + 1;
}

样品

int r5 = rand_special_50percent(10, 5);

int preferred_low_value_max = 2;
int r012 = rand_low_50percent(10, preferred_low_value_max);

高级:

如果n高于RAND_MAX/2,则需要额外调用rand()

使用rand()%n时,除非(RAND_MAX+1u)%n == 0nRAND_MAX+1的除数),否则会引入偏差。上面的代码不能弥补这一点。

答案 4 :(得分:1)

C ++ 11解决方案(不是最佳但很简单)

std::piecewise_constant_distribution可以为每个间隔的给定间隔和权重生成随机实数(浮点数或双精度数)。 不是最佳的,因为 此解决方案正在生成double并将double转换为int 。同样 从[0,3] 100个样本中获得50个不保证,但保证约50个样本。

对于您的情况:2个时间间隔 - [0,3), [3,100)及其权重[1,1] 等权重,约为[0,3)的数字的50%和[3,100)的约50%

#include <iostream>
#include <string>
#include <map>
#include <random>

int main()
{
    std::random_device rd;
    std::mt19937 gen(rd());

    std::vector<double> intervals{0,  3, 3, 100};
    std::vector<double> weights{  1,  0,  1};
    std::piecewise_constant_distribution<> d(intervals.begin(), intervals.end(), weights.begin());

    std::map<int, int> hist;
    for(int n=0; n<100; ++n) {
        ++hist[(int)d(gen)];
    }
    for(auto p : hist) {
        std::cout << p.first << " : generated " << p.second << " times"<< '\n';
    }
}
Output:
0 : generated 22 times
1 : generated 19 times
2 : generated 16 times
4 : generated 1 times
5 : generated 2 times
8 : generated 1 times
12 : generated 1 times
17 : generated 1 times
19 : generated 1 times
22 : generated 2 times
23 : generated 1 times
25 : generated 1 times
29 : generated 1 times
30 : generated 2 times
31 : generated 1 times
36 : generated 1 times
38 : generated 1 times
44 : generated 1 times
45 : generated 1 times
48 : generated 1 times
49 : generated 1 times
51 : generated 1 times
52 : generated 1 times
53 : generated 1 times
57 : generated 2 times
58 : generated 3 times
62 : generated 1 times
65 : generated 2 times
68 : generated 1 times
71 : generated 1 times
76 : generated 2 times
77 : generated 1 times
85 : generated 1 times
90 : generated 1 times
94 : generated 1 times
95 : generated 1 times
96 : generated 2 times