C++ 在两个具有一定均值的数字之间获得一组随机数。

C++ 在两个具有一定均值的数字之间获得一组随机数。,c++,c,algorithm,random,random-sample,C++,C,Algorithm,Random,Random Sample,问题:在两个值之间获得一组具有一定平均值的随机数 假设我们得到n个随机数,其中的数字在1到100之间。我们的平均值是25 我的第一种方法是有两种模式,其中我们有高于平均值和低于平均值,其中第一个随机数是初始范围1和100。随后的每个数字都将检查总数。如果总和高于平均值,我们转到case overmean,然后得到一个介于1和25之间的随机数。如果总和低于平均值,我们将按低于平均值的大小写,然后得到一个介于26和100之间的随机数 我需要一些关于如何处理这个问题的想法,除了原油,得到一个随机数,把

问题:在两个值之间获得一组具有一定平均值的随机数

假设我们得到n个随机数,其中的数字在1到100之间。我们的平均值是25

我的第一种方法是有两种模式,其中我们有高于平均值和低于平均值,其中第一个随机数是初始范围1和100。随后的每个数字都将检查总数。如果总和高于平均值,我们转到case overmean,然后得到一个介于1和25之间的随机数。如果总和低于平均值,我们将按低于平均值的大小写,然后得到一个介于26和100之间的随机数

我需要一些关于如何处理这个问题的想法,除了原油,得到一个随机数,把它加到总数中,然后得到平均值。如果它高于所讨论的平均值,我们得到一个低于平均值的随机数,依此类推。虽然它确实有效,但似乎不是最好的方法


我想我应该复习一下概率来接近这个随机数发生器

编辑:这将生成1到100范围内的数字,理论平均值为25.25。它通过使用范围为1到100的随机模量来实现这一点。请注意,要求的平均值为25,这并不完全是范围1..100的四分之一

OP想要一种根据平均值小于或大于25来改变下一个数字的方法,但这提供了一些可预测性——如果平均值大于25,那么你知道下一个“随机”数字将小于25

代码中的随机计算是非常简单的一行

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#define RUNS 10000000
#define MAXN 100

int main() {
    int n, i, sum = 0, min = MAXN, max = 0;
    int freq[MAXN+1] = {0};
    srand((unsigned)time(NULL));
    for(i = 0; i < RUNS; i++) {
        n = 1 + rand() % (1 + rand() % 100);        // average modulus is (1 + MAX) / 2
        if(max < n) {
            max = n;                                // check that whole range is picked
        }
        if(min > n) {
            min = n;
        }
        freq[n]++;                                  // keep a tally
        sum += n;
    }

    // show statistis
    printf("Mean = %f, min = %d, max = %d\n", (double)sum / RUNS, min, max);
    for(n = MAXN; n > 0; n--) {
        printf("%3d ", n);
        for(i = (freq[n] + 5000) / 10000; i > 0; i--) {
            printf("|");
        }
        printf("\n");
    }
    return 0;
}

OP没有说明需要什么样的分布,例如,两条以25为轴心的直线,或者25的每边的分布相等。然而,这个解决方案很容易实现。

实现这一点的方法有无数种。例如,生成3个介于1和100之间的随机数(
std::uniform\u int\u distribution
),并取其中的最小值(
std::min(a,b,c)

显然,对于平均值75,您需要选择最多3个数字


这种方法的好处是每个结果都独立于以前的结果。这完全是随机的。

你必须进入一些概率理论。判断随机序列的方法有很多。例如,如果你降低偏差,你会得到一个三角形的图形序列,它最终会被证明不是真正随机的。因此,除了获得随机生成器并丢弃您不喜欢的序列之外,实际上没有太多的选择。

选择一些好的分布并使用它。说。使用
B(99,24/99)
, 因此采样值在0到99之间,参数
p
等于24/99

所以,如果你有一个从B来的样本,那么你所需要的就是加上1 在1到100之间

二项式的平均值为
p*n
,在这种情况下等于24。因为你要加1,你的平均值是25。C++11在 标准库

一些代码(未测试)

#包括
#包括
int main(){
std::默认随机引擎生成器;
标准:二项分布(99,双(24)/双(99));
对于(int i=0;i!=1000;++i){
整数=配电(发电机)+1;
std::cout假设一个公平的
随机(a,b)
函数(这个问题不应该是关于哪个随机函数更好),然后简单地限制它的范围应该是一个好的开始,比如

const int desiredCount = 16;
const int deiredMean = 25;
int sumValues = random(a,b);
int count = 1;

while (count < desriredCount - 1) {
     int mean = sumValue/count;
     int nextValue = 0;
     if (mean < desiredMean) // Too small, reduce probablity of smaller numbers
          nextValue = random(a+(desiredMean-mean)/(desriredCount-count),b);
     else //too large, reduce probability of larger numbers
          nextValue = random(a,b-(mean-desiredMean)/(desriredCount-count));
     sumValue += nextValue;
     count += 1;
}
int lastValue = desiredMean*desriredCount - sumValue/count;
sumValue += lastValue;
count += 1;
const int desiredCount=16;
恒量平均值=25;
int sumValues=随机(a,b);
整数计数=1;
而(计数
注意:以上内容未经检验,我的想法是,调整上限和下限可能不够积极,不足以达到这一目的,但我希望我能让你继续


某些边界条件,例如,如果您只需要2个数字和0到100之间数字的平均值25,则初始随机数不能大于50,因为这使得无法选择第二个(最后一个)数字——因此,如果您希望algo在所有情况下都能给出准确的平均值,则需要进行更多的调整。

让我们将范围分为左右两部分。使用与另一半的相对宽度相对应的频率部分的值

int Leruce_rand(int min, int mean, int max) {
  int r = rand()%(max - min + 1);
  if (r < mean) {
    // find number in right half
    return rand()%(max - mean + 1) + mean;
  } else {
    // find number in left half
    return rand()%(mean - min) + min;
  }
int-Leruce\u rand(int-min,int-mean,int-max){
int r=rand()%(最大值-最小值+1);
if(r
假设
mean
是右半部分的一部分。此快速解决方案可能有小偏差

根据OP的值,大致上,左半部分的平均值为12.5,占75%,右半部分的平均值为62.5,占25%,占25%


这种方法不同于OP的方法,OP的方法是“每个后续的数字都会检查总和。如果总和高于平均值,则我们转到case overmean,然后得到一个介于1和25之间的随机数。”因为这绝对防止了一组高于或低于平均值的事件发生。对于RNG,生成的值不应偏向于先前生成值的历史记录。

OP需要一组符合特定标准的数字

考虑生成一个
const int desiredCount = 16;
const int deiredMean = 25;
int sumValues = random(a,b);
int count = 1;

while (count < desriredCount - 1) {
     int mean = sumValue/count;
     int nextValue = 0;
     if (mean < desiredMean) // Too small, reduce probablity of smaller numbers
          nextValue = random(a+(desiredMean-mean)/(desriredCount-count),b);
     else //too large, reduce probability of larger numbers
          nextValue = random(a,b-(mean-desiredMean)/(desriredCount-count));
     sumValue += nextValue;
     count += 1;
}
int lastValue = desiredMean*desriredCount - sumValue/count;
sumValue += lastValue;
count += 1;
int Leruce_rand(int min, int mean, int max) {
  int r = rand()%(max - min + 1);
  if (r < mean) {
    // find number in right half
    return rand()%(max - mean + 1) + mean;
  } else {
    // find number in left half
    return rand()%(mean - min) + min;
  }
#include <stdio.h>
#include <stdlib.h>

void L_set(int *set, size_t n, int min, int mean, int max) {
  assert(n > 0);
  assert(min >= 0);
  assert(mean >= min);
  assert(max >= mean);

  size_t i;
  long long diff;
  long long sum_target = n;
  unsigned long long loop = 0;
  sum_target *= mean;
  int range = max - min + 1;
  do {
    loop++;
    long long sum = 0;
    for (i = 1; i < n; i++) {
      set[i] = rand() % range + min;
      sum += set[i];
    }
    diff = sum_target - sum;  // What does the final number need to be?
  } while (diff < min || diff > max);  
  set[0] = (int) diff;

  printf("n:%zu min:%d mean:%2d max:%3d loop:%6llu {", n, min, mean, max, loop);
  for (i = 0; i < n; i++) {
    printf("%3d,", set[i]);
  }
  printf("}\n");
  fflush(stdout);
}

int main(void) {
  int set[1000];
  L_set(set, 10, 1, 2, 4);
  L_set(set, 16, 1, 50, 100);
  L_set(set, 16, 1, 25, 100);
  L_set(set, 16, 1, 20, 100);
  return 0;
}
n:10 min:1 mean: 2 max:  4 loop:     1 {  4,  2,  4,  3,  2,  1,  1,  1,  1,  1,}
n:16 min:1 mean:50 max:100 loop:     2 { 45, 81, 24, 50, 93, 65, 70, 52, 28, 91, 25, 36, 21, 45, 11, 63,}
n:16 min:1 mean:25 max:100 loop:  3257 { 52,  1, 15, 70, 66, 30,  1,  4, 26,  1, 16,  4, 48, 42, 19,  5,}
n:16 min:1 mean:20 max:100 loop:192974 { 24, 10, 13,  3,  3, 53, 22, 12, 29,  1,  7,  6, 90, 11, 20, 16,}