具有不同权重的随机值

时间:2015-12-08 20:17:46

标签: asp.net-mvc entity-framework-6

这是一个关于实体框架的问题,一直困扰着我。

我有一张名为奖品的桌子,有不同的奖品。一些有较高的,一些有较低的货币价值。它的简单表示就是这样:

+----+---------+--------+
| id |  name   | weight |
+----+---------+--------+
|  1 | Prize 1 |     80 |
|  2 | Prize 2 |     15 |
|  3 | Prize 3 |      5 |
+----+---------+--------+

重量是这种情况,我希望这个项目随机选择。

我一次选择一个随机奖品:

var prize = db.Prizes.OrderBy(r => Guid.NewGuid()).Take(1).First();

我想要做的是使用权重来确定随机项目返回的可能性,因此Prize 1将返回80%的时间,Prize 2 15%,依此类推。< / p>

我认为这样做的一种方法是将数据库上的奖金与重量一样多。与Prize 1相比,具有80次Prize 3的那种方式返回的可能性更高,但这不一定完全正确。

必须有更好的方法来做到这一点,所以我想知道你是否可以帮助我解决这个问题。

提前致谢

2 个答案:

答案 0 :(得分:0)

通常我不会在数据库中这样做,而是使用代码来解决问题。 在你的情况下,我会生成1到100之间的随机数。如果生成的数字在1到80之间,那么第一个获胜,如果它在81到95之间,那么第二个获胜,如果在96到100之间最后一场胜利。 因为随机数可以是从1到100的任意数字,每个数字有1%的机会被击中,那么你可以通过给出随机数落入的范围来管理获胜机会。 希望这可以帮助。 亨利

答案 1 :(得分:0)

这可以通过为三个(通常是n个)项目创建垃圾箱,然后选择要在其中一个垃圾箱中放置的选定随机数来完成。

可能有一个统计库可以为你做这件事,即按比例从n个箱子中选择一个箱子。

可以像下面这样实施一个不限制三个奖品/重量的解决方案:

//All Prizes in the Database
var allRows = db.Prizes.ToList();
//All Weight Values
var weights = db.Prizes.Select(p => new { p.Weight });
//Sum of Weights
var weightsSum = weights.AsEnumerable().Sum(w => w.Weight);

//Construct Bins e.g. [0, 80, 95, 100]
//Three Bins are: (0-80],(80-95],(95-100]
int[] bins = new int[weights.Count() + 1];
int start = 0;
bins[start] = 0;
foreach (var weight in weights) {
    start++;
    bins[start] = bins[start - 1] + weight.Weight;
}

//Generate a random number between 1 and weightsSum (inclusive)
Random rnd = new Random();
int selection = rnd.Next(1, weightsSum + 1);

//Assign random number to the bin
int chosenBin = 0;
for (chosenBin = 0; chosenBin < bins.Length; chosenBin++)
{
    if (bins[chosenBin] < selection && selection <= bins[chosenBin + 1])
    {
        break;
    }
}

//Announce the Prize
Console.WriteLine("You have won: " + allRows.ElementAt(chosenBin));