【问题标题】:Generate random number given a probabilty the higher the probability is the higher the result给定概率生成随机数,概率越高结果越高
【发布时间】:2021-08-27 19:35:44
【问题描述】:

我正在做一个简单的项目,我有这个方法:

public int generatePeople(float luck, int min, int max) {
    SecureRandom sr = new SecureRandom();
    int people = 0;
    // generate random people
    return people;
}

我想在最小值和最大值之间生成一定数量的人,但是人数会根据运气变量增加或减少,这应该类似于高斯,但我不知道如何在 Java 上做到这一点.

根据运气的值,区间的中心会有所不同,例如具有luck = 0.5f,它更有可能在(min + max)/2(区间的中心)附近具有值,而具有luck = 0.25f或@ 987654326@ 会将值的中心移动到左侧(min + max)/4 或右侧3*(min+max)/4,这意味着它更有可能从左侧或右侧获取值。

【问题讨论】:

  • depending on the variable luck, 它应该如何依赖?
  • @IłyaBursov 例如,运气越高,对人的重视程度就越高
  • 生成一个0-luck范围内的随机数,然后再生成一个min-max范围内的随机数,然后将它们相加。检查新值是否大于最大值。如果是返回最大值,如果不是返回值
  • luck 的值是什么意思?例如。很倒霉,你的意思是你总是得到min,但是luck的值是什么“倒霉”? 0? -Infinity?同样,非常好的运气意味着总是得到max,但那是1100+Infinity 还是别的什么?

标签: java random probability


【解决方案1】:

我们可以生成一个从 min 到 max 的随机 int 数

int randomInt = sr.nextGaussian() * (max - min) + min;

然后添加运气的影响,我们可以添加移位值。 考虑到运气是一个从 0 到 1 的浮点数,如果运气是 0.5,它必须没有影响,我们可以通过以下方式实现:

int people = randomInt + (luck - 0.5f) * (sr.nextGaussian() * (max - min) + min);

但是,通过添加一些东西,我们可以超过最小值或最大值。为了避免这种情况,我们可以添加一个超过检查并在超过的情况下分配最小值或最大值:

people = Math.min(people, max);
people = Math.max(people, min);

【讨论】:

  • 拒绝采样(拒绝超出范围的值并重试)可能比钳制超出范围的值更好。否则,最小值和最大值可能会过于频繁地出现。
【解决方案2】:

假设 min,max 范围包括在内,则有 span = max-min+1 可能的值。一种方法是定义高斯概率密度函数 (PDF),以 luck * span 为中心,sigma 为,例如,span/2 - 您可以改变它以改变中心周围分布的紧密度.

然后,您将使用 PDF 为 span 范围内的每个可能值计算“权重” - 分布中心附近的值将获得更高的权重 - 并使用标准 technique 进行选择一个范围内的随机值,其中每个值都有一个相关的权重。

这里有一些 Java 代码来说明。

static int generatePeople(double luck, int min, int max) 
{
    int span = max - min + 1;
    
    double mean = luck * span;
    double sigma = span / 2;
    
    double[] weights = new double[span];
    double totWeight = 0;
    for(int i=0; i<span; i++) 
    {
        weights[i] = pdf(mean, sigma, i+0.5);
        totWeight += weights[i];
    }
    
    double rnd = Math.random()*totWeight;
    for(int i=0; i<span; i++) 
    {
        if(rnd < weights[i]) return min+i;
        rnd -= weights[i];
    }   
    
    return max;
}
    
static double pdf(double mean, double sigma, double x)
{
    double e = (mean - x) / sigma;
    return Math.exp(-(e*e)/2)/(sigma*Math.sqrt(2*Math.PI));
}

我们可以通过生成大量值并检查minmax 之间的分布来说明给定的“luck”值。

static void test(double luck, int min, int max)
{
    int[] score = new int[max-min+1];
    for(int i=0; i<1000*score.length; i++)
        score[generatePeople(luck, min, max)-min]++;
    for(int i=0; i<score.length; i++)
    {
        System.out.println(min+i + " : " + score[i]);
    }
}

输出:

test(0.5, 0, 9);

给予:

0 : 786
1 : 878
2 : 1059
3 : 1110
4 : 1152
5 : 1162
6 : 1106
7 : 1020
8 : 962
9 : 765

虽然

test(0.25, 0, 9);

给予:

0 : 1195
1 : 1236
2 : 1285
3 : 1284
4 : 1146
5 : 1078
6 : 904
7 : 771
8 : 610
9 : 491

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-01-06
    • 2011-05-24
    • 2012-12-04
    • 1970-01-01
    • 2014-10-06
    • 2013-05-13
    相关资源
    最近更新 更多