微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

给定概率生成随机数,概率越高结果越高

如何解决给定概率生成随机数,概率越高结果越高

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

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(区间的中心)附近有值,而有 { {1}} 或 luck = 0.25f 将移动左侧 luck = 0.75f 或右侧 (min + max)/4 的值的中心,这意味着它更有可能具有来自左侧或右侧。

解决方法

我们可以用

生成一个从最小值到最大值的随机整数
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);
,

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

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

这里有一些 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 之间的分布来说明这种方法的行为。

static void test(double luck,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,9);

给出:

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

虽然

test(0.25,9);

给出:

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

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。