【问题标题】:Generating Uniform Random Deviates within a given range在给定范围内生成均匀随机偏差
【发布时间】:2010-10-01 13:29:48
【问题描述】:

我想在给定范围内生成均匀分布的随机整数。我使用的解释型语言有一个内置的快速随机数生成器,它返回一个介于 0(含)到 1(含)范围内的浮点数。不幸的是,这意味着我不能使用 standard solution seen in another SO question(当 RNG 返回 0(含)到 1(不含)之间的数字时)在给定范围内生成均匀分布的随机整数:

result=Int((highest - lowest + 1) * RNG() + lowest)

目前我能看到的唯一合理的方法是在极少数情况下随机数生成器返回 1 来请求一个新数字。

但如果有人知道更好的方法,我会很高兴听到它。

罗伯

注意:将现有的随机数生成器转换为这种语言会导致速度非常慢,所以恐怕这不是一个可行的解决方案。

编辑:链接到实际的 SO 答案。

【问题讨论】:

  • 您还没有解释为什么上面的解决方案不起作用。如果随机数生成器是随机数的良好近似,那么其结果的分布应该是均匀的,计算的结果也是如此。
  • 因为 RNG 的范围是 0(含)到 1(含),我们最终可能会得到 result=highest+1(即超出所需范围)

标签: language-agnostic random


【解决方案1】:

大概您对速度非常感兴趣,否则您只会在每次 RNG 调用时都接受条件测试。无论如何,任何其他替代方案都可能会比分支慢...

...除非您确切知道 RNG 的内部结构是什么。特别是,它的返回值是多少?如果它们不是 IEEE-754 浮点数或双精度数,我表示同情。如果是,它们中有多少真正的随机性?您会期望浮点数为 24,双精度数为 53(尾数位数)。如果这些是天真的生成的,您可以使用移位和掩码从它们中破解一个普通的旧随机整数生成器,然后在您的函数中使用它(取决于您的范围的大小,您可以使用如果您有这样的生成器,则需要更多的班次和掩码以避免任何分支)。如果您有一个高质量的生成器,它可以生成完整的 24 位或 53 位随机数,那么通过一次乘法,您可以将它们从 [0,1] 转换为 [0,1):只需乘以可生成的最大浮点数- 小于 1 的点数,你的范围问题就消失了。如果尾数没有完全填充随机位,这个技巧仍然有效,但您需要做更多的工作才能找到正确的乘数。

您可能想查看C source to the Mersenne Twister 以了解他们对类似问题的处理。

【讨论】:

  • 现在我正在为每个调用实现条件。我只是想知道是否有更好的方法。我曾考虑乘以可能不是 1 的最大浮点数,但我认为这可能会将可能不是 0 的最小浮点数转换为 0,并创建非均匀分布。
  • 是的,这些技巧可能会影响 2^-53 级别的随机性。但是,无论如何您都将结果转换为整数,因此最终分布不太可能发生变化。如果你真的需要 2^-53 级别的完美,你可能还是想要一种不同的语言。
【解决方案2】:

我不明白为什么需要+ 1。如果随机数生成器在 [0,1] 区间内提供均匀分布的值,那么...

result = lowest + (rng() * (highest - lowest))

应该给你一个最低值之间的不均匀分布

rng() == 0, result = lowest + 0 = lowest

最高

rng() == 1, result = lowest + highest - lowest = highest

包含+1表示生成数的上限可以高于最高

rng() == 1, result = lowest + highest - lowest + 1 = highest + 1.

生成的值分布将与随机数的分布相同,因此均匀性取决于随机数生成器的质量。

根据您在下面的评论,您正确地指出 Int() 将是尾部不平衡分布的来源。最好使用 Round() 到最接近的整数或脚本语言中的任何等效值。

【讨论】:

  • 这是不正确的,例如最低 = 0 和最高 = 9。当 RNG=1 时您只会输出 9,但当 RNG 的输出介于 0 和 0.1 之间时会输出 0
  • 但是 +1 也不正确,因为当它为 1 时(这应该以均匀的随机概率发生,与 0 和 0.1 之间的所有值相同)那么答案不是 9 ,但是 10。在我看来,您需要的不是将值整数化,而是将其四舍五入到最接近的整数。
  • 只有当 RNG 返回从 O(包括)到 1(不包括)的数字时,标准解决方案才是正确的。我将编辑问题以使其更清楚。
  • 您假设在 rng()==1 时,尾部不平衡的问题需要一个 +1 和一个 frig。问题不是来自那个,而是来自向下舍入的 Int() 。如果您四舍五入到最接近的数字,那么我在上面发布的解决方案可以精确地工作。另一篇文章中的“标准”解决方案是错误的。
  • 如果您的 RNG 提供的数字在 [0,1) 范围内,那么标准解决方案是正确的。如果您不相信我,请尝试一下。但是,当 RNG 提供 [0,1] 范围内的数字时,标准解决方案是不正确的。
猜你喜欢
  • 2010-09-22
  • 1970-01-01
  • 2017-01-01
  • 2017-07-13
相关资源
最近更新 更多