我有一个包含10个值的数组。这些值中的每一个都代表赢得某些东西的百分比。例如,第1行有50%的机会赢得某些东西。 有什么优雅的方法可以实现呢?
我用数据源的值填充数组:
for (let i = 0; i < 10; i++) {
this.power[i] = this.dataSource.data[i].power;
}
能力阵列代表每个人获胜的概率。第1行:50%第2行:10%,... 我想要的输出是计算概率后的获胜行。例如,第1行的获胜几率很高->我获得1作为输出的几率更高。
答案 0 :(得分:1)
我将您的问题解释为:给定一个概率数组(可能未规范化(即,它们可能未加到1.0)),该数组中将产生一个随机索引,该随机索引的产生机会与该概率成正比。该索引。
这意味着您需要在某个地方使用随机数生成器。默认情况下,我将使用Math.random()
,但您可以将其替换为具有相同合同的任何随机数生成器:一个无参数函数,该函数生成均匀分布在0和1之间的数字。
这就是我要做的:
// probabilities: array of (possibly not normalized) probabilities like [4,3,2,1]
// randomGenerator: function producing a random number, uniform distribution from 0≤x<1
function randomIndex(
probabilities: number[],
randomGenerator: () => number = Math.random
): number {
// get the cumulative distribution function
let acc: number = 0;
const cdf = probabilities
.map(v => acc += v) // running total [4,7,9,10]
.map(v => v / acc); // normalize to max 1 [0.4,0.7,0.9,1]
// pick a random number between 0 and 1
const randomNumber = randomGenerator();
// find the first index of cdf where it exceeds randomNumber
// (findIndex() is in ES2015+)
return cdf.findIndex(p => randomNumber < p);
}
这里的想法是将list of probabilities变成更像cumulative distribution的东西,其中索引i
的元素表示随机选择的索引小于或等于i
。因此,如果您的概率为[4, 3, 2, 1]
(归一化为[0.4, 0.3, 0.2, 0.1]
),则累积分布类似于[0.4, 0.7, 0.9, 1.0]
。然后,您只需要查找累积分布的第一个元素,该元素超过0到1之间的某个随机数。使用上面的[0.4, 0.7, 0.9, 1.0]
示例,如果随机数在0到0.4之间,则索引将为{{1 }}。如果介于0.4和0.7之间,则索引将为0
。如果介于0.7和0.9之间,则索引将为1
。如果介于0.9和1.0之间,则索引将为2
。您可以看到产生每个索引的概率如何与原始3
列表中的值成比例。
让我们尝试一下您的示例,方法是运行[4, 3, 2, 1]
一万次,并将每个索引的命中频率与概率进行比较:
randomIndex()
我觉得合理。好的,希望对您有所帮助。祝你好运!