-2

我用 Javascript 编写了一个显示随机图片的小函数。返回图片编号的实际行如下所示:

num = Math.floor(Math.random() * RNDGALSIZE);

目前 RNDGALSIZE = 72。

但是,我觉得有些图片经常被点击,而有些图片很长时间没有出现,所以我写了一个循环来生成num一些次数,并记录每个值num出现的次数。结果如下:

2, 1, 2, 1, 1, 3, 1, 2, 2, 2,    // num = 0 to 9
2, 1, 0, 1, 0, 2, 2, 1, 0, 1,    // num = 10 to 19
1, 2, 0, 1, 0, 0, 1, 1, 2, 1,    // num = 20 to 29
1, 0, 1, 2, 0, 2, 1, 0, 0, 0,    // num = 30 to 39
2, 2, 3, 3, 0, 1, 1, 1, 0, 3,    // num = 40 to 49
2, 1, 2, 1, 3, 2, 3, 2, 1, 1,    // num = 50 to 59
2, 1, 1, 0, 0, 2, 2, 1, 0, 1,    // num = 60 to 69
3, 1                             // num = 70 and 71

如您所见,没有出现超过 3 次的值,并且根本没有出现 16 个值。虽然有些值可能不会出现,但我认为 16 已经太多了。我的方法有什么问题吗?

更新:

一会儿:

4, 4, 3, 6, 5, 5, 3, 3, 2, 2,
2, 2, 2, 2, 3, 5, 3, 1, 4, 2,
4, 3, 0, 1, 1, 0, 1, 4, 4, 4,
2, 0, 5, 3, 0, 4, 2, 0, 2, 1,
2, 3, 4, 3, 2, 4, 3, 2, 0, 5,
4, 4, 4, 2, 3, 4, 4, 4, 5, 1,
2, 2, 4, 2, 0, 3, 4, 2, 2, 1,
4, 1,

如您所见,虽然 3 被击中 6 次,但数组中仍有 7 个零:/

4

3 回答 3

3

(这是为了详细说明lossleader的答案。)

p[n][k]表示经过n试验后,将出现完全k不同的值(72 个)的概率。很难给出一个精确的封闭式表达式,但我们可以使用动态编程很容易地计算它:

var p = [];

p[0] = [];
p[0][0] = 1; // after 0 trials, 100% chance that 0 values have appeared
for(var k = 1; k <= 72; ++k) {
    p[0][k] = 0
}

for(var n = 1; n < 1000; ++n) {
    p[n] = [];
    p[n][0] = 0;
    for(var k = 1; k < n && k <= 72; ++k) {
        p[n][k] = p[n-1][k] * k / 72 + p[n-1][k-1] * (72-k+1) / 72;
    }
    if(n <= 72) {
        p[n][n] = p[n-1][n-1] * (72-n+1) / 72;
    }
    for(var k = n + 1; k <= 72; ++k) {
        p[n][k] = 0;
    }
}

n鉴于此,我们可以计算在试验之后,我们仍然至少有z“零”(甚至没有出现过一次的值)的概率:

function probabilityAfterNTrialsOfAtLeastZZeroes(n, z) {
    var ret = 0;
    for(var k = 0; k <= 72 - z; ++k) {
        ret += p[n][k];
    }
    return ret;
}

因此,经过 91 次试验,我们仍有 16 个或更多“零”的概率为probabilityAfterNTrialsOfAtLeastZZeroes(91, 16),即 0.959,即 96%。(实际上你有这么有点令人惊讶:有 17 个或更多“零”的概率是 0.914,所以有 16 个或更少的概率只有 8.6%。)

同样,经过 194 次试验后,我们仍有 7 个或更多“零”的概率为probabilityAfterNTrialsOfAtLeastZZeroes(194, 7),即 0.179,即 18%。因此,在 194 次试验之后,您通常会期望少于 7 个“零”,但如果您多次重复该实验,您会期望几乎每五次就有 7 个或更多“零”。

我们还可以计算n试验后预期的“零”数:

function expectedZeroesAfterNTrials(n) {
    var ret = 0;
    for(var z = 0; z <= 72; ++z) {
        ret += z * p[n][72-z];
    }
    return ret;
}

在 91 次试验之后,我们期望expectedZeroesAfterNTrials(91)“零”,即 20.164,在 194 次试验之后,我们期望 4.775“零”。

于 2013-07-06T18:05:31.020 回答
1

你的数字看起来很合理,

Math.pow((71/72),194)*72 // odds of missing a number ^ tries * number of slots
4.774719247726743

由于我们无法获得分数,因此如果我们生活在“确定性随机”世界中,您应该有 5 个而不是 7 个“零”。

相反,您应该只选择不替换,然后在 0 处重新启动池。

编辑一个可以从 jsconsole 运行的快速而肮脏的 100 测试计数:

function do_test() { x = []; for (var i = 0 ; i < 72 ; i++) x.push(0); for (var j = 0; j < 194; j++) x[Math.floor(Math.random()*72)]++; count = 0; for (var i = 0 ; i < 72 ; i++) if (!x[i]) count++; return count;}


function do_tests(n) { y = []; for (var i = 0; i < n; i++) y.push(do_test()); return y;}

z = do_tests(100)

[5, 5, 3, 6, 4, 3, 2, 4, 3, 3, 4, 5, 2, 5, 5, 3, 7, 3, 3, 4, 6, 4, 7, 4, 3 , 7, 6, 5, 8, 3, 3, 4, 5, 3, 3, 3, 8, 3, 4, 7, 8, 4, 6, 3, 4, 3, 4, 3, 2, 7 , 6, 7, 7, 5, 3, 6, 1, 3, 6, 5, 3, 3, 5, 4, 4, 5, 3, 4, 6, 6, 4, 3, 3, 7, 4 , 11, 6, 5, 9, 5, 3, 6, 7, 6, 9, 2, 1, 7, 3, 4, 4, 6, 6, 7, 7, 5, 2, 5, 9, 6 ]

j = 0; for (var i = 0; i < 100; i++) j+=z[i];

473 // 所以 4.73 个零槽是这 100 次运行的平均值...

于 2013-07-06T17:01:25.627 回答
0

因此,解决方案是跟踪一个数字被命中的频率,如果随机生成器命中一个已经经常被命中的数字,则提供一个经常被忽略的数字……</p>

var minhit = Number.MAX_VALUE;
var maxhit = 1;
var index_min = 0;
for (i=0; i<RNDGALSIZE; i++)
{
  if (imgnum[i] < minhit)
  {
    minhit = imgnum[i];
  index_min = i;
  }
  else if (imgnum[i]>maxhit)
  {
    maxhit = imgnum[i];
  }
}
var num = Math.floor(Math.random() * RNDGALSIZE);
if (imgnum[num] == maxhit)
{
  num = index_min;
}
imgnum[num]++;

结果:

2, 2, 1, 2, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 2, 1, 1,
2, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 2, 1,
1, 1, 1, 1, 1, 1, 2, 1, 1, 1,
1, 1, 
于 2013-07-06T17:07:44.647 回答