【问题标题】:JavaScript weighted random or percent of the timeJavaScript 加权随机或时间百分比
【发布时间】:2012-06-24 07:20:31
【问题描述】:

我有一个每 100 毫秒运行一次的 Node.js 进程 (setInterval)。我有一些我想每隔 x 时间采取的行动。例如,2% 的时间做 X,10% 的时间做 Y,等等。

现在,我基本上是这样做的:

var rand = Math.floor(Math.random() * (1000 + 1));

if(rand > 900) {  // Do something }

if(rand > 950) {  // Do something }

问题是它非常不一致。您可能希望if(rand > 900) 至少接近 10% 的时间,但有时可能连续 10 倍或根本没有。

如果我们假设 100 毫秒的时间间隔是固定的,那么任何人都可以提出更准确的更好解决方案的建议。

谢谢!

编辑:基于 Dr. Dredel 的 cmets:

var count = 0;
setInterval(function(){

    if(count++ % 4 == 0) {
       console.log('25% of the time');
    }

}, 100);​

【问题讨论】:

  • 为您要执行的每个单独的子流程创建一个setInterval 是不可能的吗?
  • 我不确定我是否明白你在问什么。您可能会随机获得 10% 的事件连续发生多次或根本不发生。
  • 欢迎来到概率世界! - en.wikipedia.org/wiki/Probability(这是一个疯狂的世界,受过教育的人可能无法理解 World of Warcraft 玩家会做什么)
  • 您似乎想控制分布,以便如果 y 在 8 次迭代中没有发生,则增加它的概率,反之,如果它在 4 次迭代中发生两次,则减少它可能性。您可能还想确保永远不会连续获得两个 y。如果你想要的话,我敢肯定有一个相当简单的算法。它不会是完全随机的,但可能就足够了。
  • 仅供参考,你可以在这里玩随机性:jsfiddle.net/jfriend00/wEufz。正如其他人所说,如果您希望在少量迭代中精确地达到 n% 的时间,那么您不能使用 random,因为它只会在大量迭代时为您提供预期的结果。

标签: javascript node.js random weighted


【解决方案1】:

如果您的间隔是固定的,我会将您的标记四舍五入到最接近的百位,然后使用与您的需求相关的那些段... 100 和 200 但不是 300-1000 来表示 2%。

如果您可以使用计数器,那么这是更明显的方法。

if(myCounter++ % 4 == 0)
    //this happens 25 percent of the time 

正如 Emil 指出的那样,概率在这里并不是正确的方法,而且我不觉得你已经嫁给了它......听起来你正在使用它,因为你没有看到更好的方法激发某事发生 x% 的时间的方法。如果我们对您有误解,您需要更详细地解释为什么在这里使用赔率。

【讨论】:

  • 谢谢!所以我在上面的问题中添加了一个例子。你是这个意思吗?如果我想在 10% 或 2% 的时间里做某事怎么办?
  • 这也是一个连续运行的区间,所以计数器最终会攀升到数不胜数——这种方法看起来还合适吗?
  • 当然...您可以随时重置计数器。如果您正在处理百分比,您可以在每次达到 100 时重置计数器。这实际上取决于您的需求粒度。如果您需要在 1% 的时间内发生某事,则需要将计数器运行到 100。如果需要在 0.1% 的时间发生,则需要将其运行到 1000。但是,如果需要运行 1/ 2 次,您的计数器永远不需要超过 2 :) 只需考虑“我需要多久一次?”。
  • 虽然这不是一个随机生成器,但它会以精确的比例返回值,因此 1:4 恰好每四次发生一次,1:5 恰好每五次发生一次,依此类推。
  • @RobG,我在 dave 的帖子中没有看到任何暗示他*希望它是随机的。看起来这只是他想出的解决方案,让它偶尔发生。
【解决方案2】:

介绍一个计数器和 BAM!现在您可以完全在 2% 的时间里拥有它!

说真的,引入某种状态是您执行“连续多次”政策的唯一方法。概率/随机性无法帮助您解决这个问题。相信随机事件不会连续多次发生是一个众所周知的神话。事实上,一个 2% 的可能性事件可能会连续发生数百万次,尽管可能性很小。

您将需要添加一个约束条件,例如“我希望事件以 x% 的概率发生,但我总是希望它在每个事件之后至少进行 y 步”。

【讨论】:

    【解决方案3】:

    如果您想保证您的操作在一定百分比的时间内发生(而不是任由偶然发生),但您希望以随机顺序选择它们,那么您可以执行类似的操作,创建一个数据结构,其中包含您想要的精确结果,以便对所有元素进行一次迭代。然后,您随机选择其中一个结果,将其从数据结构中删除,随机选择另一个结果等等......

    如果您使用每个结果的适当百分比作为初始数据结构的种子,那么您将根据该规则获得结果,并且对于每次完整迭代,您将获得每个结果的准确数量,但它们将被选中顺序是随机的,每次的顺序都不一样。

    如果您希望该过程一遍又一遍地重复,您可以在每次完成一个完整的迭代时重新开始。

    var playProbabilities = [
        {item: "A", chances: 3},
        {item: "B", chances: 2},
        {item: "C", chances: 1},
        {item: "D", chances: 2},
        {item: "E", chances: 1},
        {item: "F", chances: 1}
    ];
    
    function startPlay(items) {
        var itemsRemaining = [];
        // cycle through the items list and populate itemsRemaining
        for (var i = 0; i < items.length; i++) {
            var obj = items[i];
            // for each item, start with the right number of chances
            for (var j = 0; j < obj.chances; j++) {
                itemsRemaining.push(obj.item);
            }
        }
        return(itemsRemaining);
    }
    
    function nextPlay(itemsRemaining) {
        if (!itemsRemaining.length) {
            return null;
        }
        // randomly pick one
        var rand = Math.floor(Math.random() * itemsRemaining.length);
        var result = itemsRemaining[rand];
    
        // remove the one we picked from the array
        itemsRemaining.splice(rand, 1);
        return(result);
    }
    
    $("#go").click(function() {
        var results = $("#results");
        var items = startPlay(playProbabilities);
        var next;
        while(next = nextPlay(items)) {
            results.append(next + "<br>");
        }
        results.append("-------------<br>");
    });
    

    这里的工作演示:http://jsfiddle.net/jfriend00/x2v63/

    如果您运行该演示,您会看到每次运行都会准确生成每个结果的所需数量,但它们是按随机顺序选择的。

    【讨论】:

    • 这是一个有趣的方法,我不确定它是否适用于这个应用程序 - 这可以用来执行 X% 的时间吗?
    • @dave - 是的,可以为 X% 的时间设置概率。我的答案中的示例有“A”:30%,“B”:20%,“C”:10%,“D”:20%,“E”:10%,“F”:10%。您可以调整每个项目的机会数以更改其概率。给定项目的概率是它的机会数除以所有机会数的总和。
    • @RobG - 在 OP 编写的任何内容中,我都没有看到任何没有连续项目的标准。这段代码的重点是保证每个项目都能获得公平的点击率,即使样本量很小。
    猜你喜欢
    • 2021-06-22
    • 2011-10-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-10
    • 1970-01-01
    • 2020-12-22
    • 1970-01-01
    相关资源
    最近更新 更多