在具有已定义概率的多个选项之间进

Sij*_*jin 3 .net c# asp.net algorithm

我有一个场景,我需要根据概率分布向用户显示相同网址的不同页面,

因此对于例如3页的分发可能是

page 1 - 30% of all users
page 2 - 50% of all users
page 3 - 20% of all users
Run Code Online (Sandbox Code Playgroud)

在决定为给定用户加载哪个页面时,我可以使用哪种技术来确保整体分布与上述匹配?

我想我需要一种从集合X {x1,x2 ...... xn}中"随机"选择一个对象的方法,除了不是所有对象同样可能预先定义对象被选中的概率.


感谢大家的投入,在做了一些原型设计之后,这就是我最终使用的内容

private static int RandomIndexWithPercentage(Random random, int[] percentages) {
    if (random == null) {
        throw new ArgumentNullException("random");
    }

    if (percentages == null || percentages.Length == 0) {
        throw new ArgumentException("percentages cannot be null or empty", "percentages");
    }

    if(percentages.Sum() != 100) {
        throw new ArgumentException("percentages should sum upto 100");
    }

    if (percentages.Any(n => n < 0)) {
        throw new ArgumentException("percentages should be non-negative");
    }

    var randomNumber = random.Next(100);
    var sum = 0;
    for (int i = 0; i < percentages.Length; ++i) {
        sum += percentages[i];
        if (sum > randomNumber) {
            return i;
        }
    }

    //This should not be reached, because randomNumber < 100 and sum will hit 100 eventually
    throw new Exception("Unexpected");
} 
Run Code Online (Sandbox Code Playgroud)

dlr*_*as2 6

生成0-9的数字.如果数字小于3,请给第一页.如果小于8,请给第2页,或者给第3页.


一些代码,可以帮助您入门:

private int ChoosePage()
{
    int[] weights = new int[] { 3, 5, 2 };
    int sum = 0;
    int i;
    for (i = 0; i < weights.Length; i++)
        sum += weights[i];
    int selection = (new Random()).Next(sum);
    int count = 0;
    for (i = 0; i < weights.Length - 1; i++)
    {
        count += weights[i];
        if (selection < count)
            return i;
    }
    return weights.Length - 1;
}
Run Code Online (Sandbox Code Playgroud)

请注意,权重不必特别加起来.如果sum= 100,则weight[i]获得页面的几率为百分之百i.但是,如果它不是,它只是相对的 - 如果weight[i]是两次weight[j],那么页面i将获得两倍于页面的命中j.这很好,因为您可以在不重新计算任何内容的情况下随意增加或减少页面流量.或者,您可以确保总和始终为N硬编码N,而不是每次都汇总所有值.我敢肯定,你可以做很多优化.