如何将权重曲线添加到随机选择中

本文关键字:随机 选择 添加 曲线 权重 | 更新日期: 2023-09-27 18:01:09

我想要一个函数,它返回两个给定值之间的随机数。问题是,我希望它总是"喜欢"较低的值而不是较高的值,以某种"曲线"上升。

所以,假设我给它数字100和1000,它可以给我这两个值之间的任何数字。。。然而,它会给我100到200之间的值,远远超过你期望的11.11%,相反,它可能会在30-40%的时间内给出这些值,而最上面的值可能只在2-4%的时间内得到。关于如何最好地解决这个问题,有什么想法吗?

语言是C#,但可能没那么重要。

如何将权重曲线添加到随机选择中

你可以对你的随机数进行平方,这会将数字加权到你的范围的底部:

public double GetWeightedRandom(int min, int max)
{
Random random = new Random();
double randomZeroToOne = random.NextDouble();
double weightedRandom = randomZeroToOne * randomZeroToOne * (max - min) + min;
return weightedRandom;
}

在我的100到1000次测试中,它给出的平均值是400,而不是550。如果你想让这个数字的权重更大,你可以对它进行立方体运算。

我建议您使用自己的自定义方式来实现随机数生成器。例如,编写一个包装类,它将创建一个介于1-100之间的随机数,如果它在1-40之间,它会返回100-200之间的随机数字,以此类推,那么你基本上会在你的数字生成中添加你自己的一组优先级。如果该值在41-100之间,它将返回一个201-1000之间的数字。您更喜欢哪种方式的

我想用y=ab^x创建一条指数曲线,这将在两个输入数字之间创建一条曲线,然后获得0和1之间的随机数,以获得沿曲线x轴的归一化位置,并返回y值。

加权随机可能就是你想要的,在这种情况下,一个很好的想象方法是考虑一个具有重复元素的列表,其中权重更高

var elements = new[]{1,1,2,2,3,3,10,11,12,13};
var rnd = elements[rnd.Next(0,elements.length-1)];

从上面可以看出,rnd等于123的可能性是10111213的两倍。

您可以使用一个函数生成相同的列表,该函数采用平面列表和相关权重:

public List<int> GenerateWeighedList(int[] list, float[] weight) {
    var weighedList = new List<int>();
    // Loop over weights
    for (var i = 0; i < weight.Length; i++) {
        var multiples = weight[i] * 100;
        // Loop over the list of items
        for (var j = 0; j < multiples; j++) {
            weighedList.push(list[i]);
        }
    }
    return weighedList;
};

所以上面的列表可以用生成

var input = new[]{1,2,3,10,11,12,13};
var weight = new[]{0.2,0.2,0.2,0.1,0.1,0.1,0.1};
var weightedList = GenerateWeighedList(input,weight);

weightedList然后可以用于从所需集合中以指定的权重生成加权随机数

我会分两步来完成。第一步-是确定你的数字是否应该降低。第二步是返回相应范围内的随机数。

public int RandomWeighted(int min, int max, int cap, int percent)
{
    Random rand = new Random();
    bool isInCap = rand.Next(0, 101) < percent;
    return isInCap? rand.Next(min, cap) : rand.Next(cap, max);
}

并将其用作:int num = RandomWeighted(100, 1000, 200, 50);这将在50%的时间内给你100-200,在其他50%的中给你200-1000