在两个具有特定均值的数字之间获取一组随机数。

时间:2016-06-03 21:29:41

标签: c++ c algorithm random random-sample

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

假设我们得到n个随机数,其中数字介于1和100之间。我们的平均值为25.

我的第一种方法是有2种模式,其中我们有aboveMean和belowMean,其中第一个随机数是初始范围1和100.每个后续数字将检查总和。如果总和高于平均值,我们转到上面的情况,然后获得1到25之间的随机数。如果总和低于平均值,我们在下面的情况下进行,然后获得26到100之间的随机数。 / p>

我需要一些关于如何在原油旁边解决这个问题的想法获得一个随机数,将其添加到总数然后得到平均值。如果它高于有问题的平均值,我们得到一个低于平均值的随机数,依此类推。虽然它确实有效,但似乎并不是最好的方法。

我猜我应该提高接近这个随机数发生器的概率。

7 个答案:

答案 0 :(得分: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;
  }

假设mean是右半部分的一部分。这种快速解决方案可能存在偏差。

给定OP的值,粗略地说,左半部分的平均值是12.5,并且在75%的时间内被称为。右边的平均值是62.5,占25%的时间:平均25。

这种方法不同于OP,“每个后续数字都将检查总和。如果总和高于平均值,我们转到上面的情况,然后获得1到25之间的随机数。”因为这绝对可以防止出现高于或低于均值的一组事件。对于RNG,生成的值应该偏向于先前生成的值的历史记录。

答案 1 :(得分:0)

实际上有很多方法可以实现这一目标。例如,生成1到100之间的3个随机数(ViewModel)并取最小值(std::uniform_int_distribution)。

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

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

答案 2 :(得分:0)

进行一些好的分发并使用它。说,Binomial distribution。使用B(99,24/99), 所以采样值在0 ... 99范围内,参数p等于24/99。

因此,如果您有来自B的常规样本,那么您只需要添加1 在他的范围1 ... 100

二项式的平均值为p*n,在这种情况下等于24.因为您加1,您的平均值将根据需要为25。 C ++ 11中有二项式RNG 标准库

一些代码(未经测试)

#include <iostream>
#include <random>

int main() {
    std::default_random_engine generator;
    std::binomial_distribution<int> distribution(99, double(24)/double(99));

    for (int i=0; i != 1000; ++i) {
        int number = distribution(generator) + 1;
        std::cout << number << std::endl;
    }

    return 0;
}

答案 3 :(得分:0)

假设一个公平的random(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;

注意:上面没有经过测试,我的想法是修剪上限和下限可能不足以咄咄逼人,但我希望我会让你去

某些边界条件,例如,如果您只需要2个数字,并且从0到100之间的数字表示25,则初始随机数不能大于50,因为这样就无法选择第二个(最后一个)数字 - 所以如果你想让算法在所有情况下都能给出精确的平均值,那么就需要进行更多的调整。

答案 4 :(得分:0)

OP需要设置符合特定条件的数字。

考虑在n范围内生成所有可能的[min max]个数字集,然后删除除了mean之外的所有集合。现在随机选择其中一组。这符合OP的目标,IMO将通过公平的随机性测试。然而,这种直接的方法可能是一项艰巨的任务。

或者,随机生成大量的集合,直到找到满足 mean 测试的集合。

以下符合OP对指定均值的要求,而不直接偏置所选的随机数。当期望的mean远离min/max平均值时,当然不是高效的方法。

#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,}

答案 5 :(得分:-1)

编辑:这会生成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;
}

节目输出显示分布/ 10000:

Mean = 25.728128, min = 1, max = 100
100
 99
 98
 97
 96 |
 95 |
 94 |
 93 |
 92 |
 91 |
 90 |
 89 |
 88 |
 87 |
 86 ||
 85 ||
 84 ||
 83 ||
 82 ||
 81 ||
 80 ||
 79 ||
 78 |||
 77 |||
 76 |||
 75 |||
 74 |||
 73 |||
 72 |||
 71 ||||
 70 ||||
 69 ||||
 68 ||||
 67 ||||
 66 ||||
 65 ||||
 64 |||||
 63 |||||
 62 |||||
 61 |||||
 60 |||||
 59 |||||
 58 ||||||
 57 ||||||
 56 ||||||
 55 ||||||
 54 ||||||
 53 ||||||
 52 |||||||
 51 |||||||
 50 |||||||
 49 |||||||
 48 |||||||
 47 ||||||||
 46 ||||||||
 45 ||||||||
 44 ||||||||
 43 |||||||||
 42 |||||||||
 41 |||||||||
 40 |||||||||
 39 ||||||||||
 38 ||||||||||
 37 ||||||||||
 36 ||||||||||
 35 |||||||||||
 34 |||||||||||
 33 |||||||||||
 32 ||||||||||||
 31 ||||||||||||
 30 ||||||||||||
 29 |||||||||||||
 28 |||||||||||||
 27 |||||||||||||
 26 ||||||||||||||
 25 ||||||||||||||
 24 ||||||||||||||
 23 |||||||||||||||
 22 |||||||||||||||
 21 ||||||||||||||||
 20 ||||||||||||||||
 19 |||||||||||||||||
 18 |||||||||||||||||
 17 ||||||||||||||||||
 16 |||||||||||||||||||
 15 |||||||||||||||||||
 14 ||||||||||||||||||||
 13 |||||||||||||||||||||
 12 ||||||||||||||||||||||
 11 |||||||||||||||||||||||
 10 ||||||||||||||||||||||||
  9 |||||||||||||||||||||||||
  8 ||||||||||||||||||||||||||
  7 |||||||||||||||||||||||||||
  6 |||||||||||||||||||||||||||||
  5 |||||||||||||||||||||||||||||||
  4 |||||||||||||||||||||||||||||||||
  3 |||||||||||||||||||||||||||||||||||||
  2 ||||||||||||||||||||||||||||||||||||||||||
  1 ||||||||||||||||||||||||||||||||||||||||||||||||||||
OP没有说明需要什么样的分布,例如两条直线在25处旋转,或者每一侧的分布可能相等。但是这个解决方案实现起来非常简单。

答案 6 :(得分:-1)

你必须进入一些概率理论。有很多方法可以判断随机序列。例如,如果你降低偏差,你会得到三角形的图形序列,最后可以证明它不是随机的。所以没有多少选择比获得随机生成器并丢弃你不喜欢的序列。