我在文章“
永无休止的随机播放序列 ”
的注释中看到了此代码。我了解基本前提,但我不知道它是如何工作的。
我需要的最大解释是while循环的前两行。
(因为它是用MATLAB编写的,所以我只能猜测该代码的功能。)
probabilities = [1 1 1 1 1 1]; unrandomness = 1; while true cumprob = cumsum(probabilities) ./ sum(probabilities); roll = find(cumprob >= rand, 1) probabilities = probabilities + unrandomness; probabilities(roll) = probabilities(roll) - 6*unrandomness; if min(probabilities) < 0 probabilities = probabilities - min(probabilities); end end
回答:
probabilities向量表示将选择数字1到6的可能性的相对权重。一开始,他们都有同等的机会被选中。我将逐步通过while循环的每一行来说明其作用:
- while循环中的第一行从probabilities向量创建累积概率。 CUMSUM函数用于沿向量的长度返回累加和,然后将其除以向量的总和(使用SUM函数求出)。在第一次通过循环时, cumprob将具有以下值:
0.1667 0.3333 0.5000 0.6667 0.8333 1.0000 请注意,这些会创建“箱”,从0到1的随机数可能会落入其中。一个数字落在给定箱中的概率等于该箱的宽度,因此,六分之一(0.1667)的机会是随机抽取的数字将落在第一个容器(从0到0.1667)或第二个容器(从0.1667到0.3333),依此类推。
- while循环中的第二行选择一个随机数(使用RAND函数),并找到cumprob中第一个元素的索引大于该值的索引(使用FIND函数)。因此, roll值是从1到6的数字。
- while循环中的第三行通过将所有相对权重向上移动来增加“非随机性”,使所有数字的概率稍微接近于相等。考虑probabilities具有以下形式的示例:
[xxx 1 xx] 其中x是大于1的某个值。在这一点上,选择值4的概率为1/(5*x+1) 。通过对所有元素加1,该概率变为2/(5*x+7) 。对于x = 3 ,4度发生从0.0625到0.0909的概率增大 ,而任何其他存在的数目减小的从0.1875到0.1818的概率。因此,这种“非随机性”用于归一化概率。
- while循环中的第四行与前一行基本相反,它通过显着降低刚刚发生的任何数字的相对权重,从而使其不太可能在后续循环中发生。由于前一行不断尝试使所有数字的出现概率恢复为相等,因此减少的出现可能性将是短暂的。
注意,从一个probabilities元素中减去的数量等于添加到前一行中所有元素的总量,从而导致probabilities矢量的总和净变化为零。这样可以使probabilities的值保持一定范围,这样它们就不会一直在增长。
- 在while循环末尾的if语句只是为了确保probabilities中的所有数字都是正数。如果向量的最小值 (使用MIN函数找到)小于零,则从向量的每个元素中减去该值。这将确保cumprob向量始终具有介于0和1之间的值。
如果将for i = 1:6 while true语句替换for i = 1:6 ,则在每次迭代结束时显示probabilities向量和roll值,然后重复运行几次代码,即可看到代码的工作方式。这是一组这样的6卷,它一次绘制数字1到6:
roll probabilities 5 | 6 6 6 6 0 6 | 4 | 7 7 7 1 1 7 | 2 | 8 2 8 2 2 8 | 1 | 3 3 9 3 3 9 | 3 | 4 4 4 4 4 10 | 6 | 5 5 5 5 5 5 请注意, probabilities的最终值如何都相等,这意味着在那一点上数字1到6再次被选择的可能性相同。
更多&回答...