【问题标题】:How to calculate the probability out of an array in Angular?如何计算Angular中数组的概率?
【发布时间】:2019-03-28 13:07:55
【问题描述】:

我有一个包含 10 个值的数组。这些值中的每一个都代表赢得某物的百分比。例如,第 1 行有 50% 的机会赢得某些东西。 什么是优雅的实现方式?

我用数据源的值填充数组:

    for (let i = 0; i < 10; i++) {
      this.power[i] = this.dataSource.data[i].power;
    }

幂数组表示每个人获胜的概率。第 1 行:50% 第 2 行:10%,... 我想要输出的是概率计算后的获胜行。因此,例如第 1 行获胜的可能性最高 --> 我得到 1 作为输出的可能性更高。

【问题讨论】:

  • 你的尝试是什么?您是否查看过过滤器
  • 没有。没有查看过滤器,但我现在会查找它。
  • 您能明确说明您期望的输出吗?你得到一个概率数组(以百分比表示),你想产生......相同的概率数组?每个元素除以 100 的数组?数组的总和?数字100? 50号? 1号?数字0.5? 42号?很难知道你在问什么。
  • 编辑问题
  • 所以你想要一个随机输出,其中数组被视为probability mass function?

标签: angular typescript probability


【解决方案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 之间,则索引将为 0。如果它介于 0.4 和 0.7 之间,则索引将为 1。如果它介于 0.7 和 0.9 之间,则索引将为 2。如果它在 0.9 和 1.0 之间,那么索引将为3。您可以看到生成每个索引的概率如何与原始[4, 3, 2, 1] 列表中的值成比例。

让我们通过运行randomIndex() 一万次并将每个索引的命中频率与概率进行比较来尝试一下您的示例:

const probabilities = [50, 10, 10, 10, 10, 2, 2, 2, 2, 2];
let hits = probabilities.map(x => 0);
const numAttempts = 10000;
for (let k = 0; k < numAttempts; k++) {
    hits[randomIndex(probabilities)]++;
}
for (let i = 0; i < probabilities.length; i++) {
    console.log("" + i + ": prob=" + probabilities[i] + 
      ", freq=" + (100 * hits[i] / numAttempts).toFixed(1));
}

/*
Example of console.log output:
0: prob=50, frequency: 49.4
1: prob=10, freq=10.3
2: prob=10, freq=10.4
3: prob=10, freq=9.9
4: prob=10, freq=10.3
5: prob=2, freq=2.2
6: prob=2, freq=1.8
7: prob=2, freq=1.8
8: prob=2, freq=1.9
9: prob=2, freq=2.1
*/

在我看来是合理的。好的,希望有帮助。祝你好运!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-04
    • 1970-01-01
    • 2020-09-24
    • 2017-12-07
    • 1970-01-01
    • 2018-08-09
    相关资源
    最近更新 更多