asp.net 在具有确定概率的多个选项之间进行选择

sczxawaw  于 2023-02-10  发布在  .NET
关注(0)|答案(2)|浏览(89)

我有一个场景,我需要根据概率分布为同一个URL向用户显示不同的页面,
因此对于例如3个页面,分布可以是

page 1 - 30% of all users
page 2 - 50% of all users
page 3 - 20% of all users

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

我在想,我需要一种从集合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");
}
mqxuamgl

mqxuamgl1#

生成一个数字0-9。如果数字小于3,给予他们第一页。如果小于8,给他们第二页,否则给他们第三页。
一些代码,让你开始:

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;
}

请注意,权重不一定要加起来,如果sum = 100,则weight[i]是得到i页的百分之th的概率,如果不是,则只是相对的--如果weight[i]weight[j]的两倍,那么页面i的点击量将是页面j的两倍,这很好,因为你可以随意增加或减少页面流量,而无需重新计算任何东西,或者,你可以确保总和总是N,并将N硬编码到中,而不是每次对所有值求和。我确信,您可以做更多的优化。

cvxl0en2

cvxl0en22#

这是我的代码,工作仔细.

public static int GetRandomIndexByPercent(params byte[] percentages)
    {
        int randomNumber = new Random().Next(1, percentages.Sum(a => a) + 1);

        for (int sum = 0, i = 0; i < percentages.Length - 1; i++)
        {
            sum += percentages[i];
            if (randomNumber <= sum) return i;
        }

        return percentages.Length - 1;
    }

也可以使用以下代码进行测试:

for (int j = 0; j < 5; j++)
        {
            var items = new int[] { 40, 20, 10, 30 };
            var items2 = new int[items.Length];

            for (int i = 1; i <= 100000; i++)
                items2[GetRandomIndexByPercent(items)]++;

            for (int i = 0; i < items2.Length; i++)
                Console.WriteLine(items[i] + " > " + (items2[i] / 1000.0));

            Console.WriteLine("\n\n");
        }

        Console.ReadKey();

相关问题