【问题标题】:Understanding "randomness"理解“随机性”
【发布时间】:2011-04-26 18:27:26
【问题描述】:

我无法理解这个,哪个更随机?

rand()

rand() * rand()

我发现这是一个真正的脑筋急转弯,你能帮帮我吗?


编辑:

直觉上我知道数学上的答案是它们是同样随机的,但我不禁认为,如果在将两者相乘时“运行随机数算法”两次,你会创造出更随机的东西而不是只做一次。

【问题讨论】:

  • “更随机”是什么意思?
  • 正如其他人所说,这两个数量没有相同的分布。请参阅 mathworld.wolfram.com/UniformProductDistribution.html 了解您实际获得的分布。将此与单个均匀随机数进行比较,其中区间中的所有值的可能性相同,因此概率密度函数是一条水平直线。
  • 我强烈推荐阅读Random Stupiditythe Daily WTF。特别是阅读this comment,他们分析了这个新随机数的输出。从中得到的信息是:对随机数的任意操作不一定会导致随机输出
  • 另外:直觉上我知道数学上的答案将是它们同样随机 - 如果你可以仅凭直觉做数学,我们就不需要所有这些该死的符号:P
  • 不要把统计和直觉带到同一方......

标签: math language-agnostic random


【解决方案1】:

只是澄清一下

尽管当您尝试发现伪随机变量或其乘法的随机性时,前面的答案都是正确的,但您应该注意,虽然 Random() 通常是均匀分布的,但 Random() * Random() 不是。

示例

这是通过伪随机变量模拟的uniform random distribution sample

        BarChart[BinCounts[RandomReal[{0, 1}, 50000], 0.01]]

虽然这是两个随机变量相乘后得到的分布:

        BarChart[BinCounts[Table[RandomReal[{0, 1}, 50000] * 
                                 RandomReal[{0, 1}, 50000], {50000}], 0.01]]

所以,两者都是“随机的”,但它们的分布非常不同。

另一个例子

2 * Random() 是均匀分布的:

        BarChart[BinCounts[2 * RandomReal[{0, 1}, 50000], 0.01]]

Random() + Random() 不是!

        BarChart[BinCounts[Table[RandomReal[{0, 1}, 50000] + 
                                 RandomReal[{0, 1}, 50000], {50000}], 0.01]]

中心极限定理

Central Limit Theorem 表明,随着项数的增加,Random() 的总和趋向于 normal distribution

只需四个字词即可:

BarChart[BinCounts[Table[RandomReal[{0, 1}, 50000] + RandomReal[{0, 1}, 50000] +
                   Table[RandomReal[{0, 1}, 50000] + RandomReal[{0, 1}, 50000],
                   {50000}],
         0.01]]  

在这里,您可以通过将 1、2、4、6、10 和 20 个均匀分布的随机变量相加来查看从均匀分布到正态分布的道路:

编辑

几个学分

感谢Thomas Ahle 在 cmets 中指出最后两张图像中显示的概率分布称为Irwin-Hall distribution

感谢Heike 的精彩torn[] function

【讨论】:

  • +1。由于 OP 可能想要均匀分布,这应该是公认的答案。如果你做了rand()+rand(),你最终会得到一个带有脂肪中心的“2d6”型分布。
  • 这很有趣,但它让我在内心深处觉得这是多么反直觉。在阅读更多有关分发的内容后,我将进行更彻底的研究。非常感谢!
  • @Trufa:也许这将有助于部分直觉,至少对于总和而言。想象一下,取一个掷骰子的“平均值”。现在想象一下取两个骰子的平均值。现在一百。当您添加更多骰子时,平均获得 1 或 6 的机会会发生什么变化?
  • @matt b 图表在 Mathematica 中是单行的。代码是每个图表之前的粗体文本。 Mathematica 是一种很棒的绘图语言!
  • @thenonhacker:是的,直方图确实表现出偏差,但它们没有表现出非随机性。有偏随机数的随机性并不低。至于用户原始问题的正确答案是,“不要试图变得聪明,你只会让事情变得更糟”,这个答案确实传达了这一点。
【解决方案2】:

我猜这两种方法都是随机的,尽管我的直觉会说rand() * rand() 的随机性较小,因为它会产生更多的零。只要rand()0,总数就变成0

【讨论】:

  • 我对使用此条的所有答案的回答是这样的:我喜欢幽默,但它必须是连续的!
  • @Andomar:不,不是。一点也不。你知道什么是CW吗?
  • @Andreas Rejbrand:CW 是一种武器,它通过否认回答者的声誉来扼杀有趣的问题。看起来它被削弱了meta.stackexchange.com/questions/392/…(这也许就是为什么会出现这个有趣的问题!)
  • @Andomar - 是的,CW 扼杀了有趣的问题,但是(来自FAQ)“声誉是对社区信任你的程度的粗略衡量。”如果您在答案中包含一个有趣的copyrighted 图片,它会让我觉得您的答案很酷,而且我可能会认为 也很酷,但这不会让您更加信任-值得 - 因此,理想情况下,不应授予任何代表。这是否意味着 CW,或者是否意味着不应该投票给答案是另一个问题。
  • 卡通中的“随机生成器”巨魔可能只是一个背诵 π 的专家,并且刚刚到达Feynman point。顺便说一句,π 位是随机的吗? :)
【解决方案3】:

两者都不是“更随机”。

rand() 基于伪随机种子(通常基于当前时间,始终在变化)生成一组可预测的数字。将序列中的两个连续数字相乘会生成一个不同但同样可预测的数字序列。

解决这是否会减少冲突,答案是否定的。由于将0 < n < 1 处的两个数字相乘,它实际上会增加碰撞。结果将是一个较小的分数,导致结果偏向频谱的低端。

一些进一步的解释。在下文中,“不可预测”和“随机”是指某人根据之前的数字猜测下一个数字将是什么的能力,即。神谕。

给定种子x,它生成以下值列表:

0.3, 0.6, 0.2, 0.4, 0.8, 0.1, 0.7, 0.3, ...

rand()会生成上面的列表,rand() * rand()会生成:

0.18, 0.08, 0.08, 0.21, ...

这两种方法总是会为同一个种子生成相同的数字列表,因此预言机同样可以预测。但是,如果您查看将两个调用相乘的结果,您会发现它们都在0.3 之下,尽管在原始序列中分布得体。由于两个分数相乘的影响,这些数字是有偏差的。结果数字总是更小,因此更可能发生碰撞,尽管仍然是不可预测的。

【讨论】:

  • +1 请注意,另一方面,rand()+rand()+rand()... 变得越来越“不那么随机”(如果随机意味着均匀分布)。
  • @Thilo 不,它没有...?如果一个随机变量均匀分布在 (0,1) 范围内,并且您对该变量进行 n 次采样,然后求和,它将恰好均匀分布在 (0,n) 范围内。
  • @Trufa 只相信rand() 实际上是随机的,不要试图“增强”它的随机性。不要多次设置种子。任何单个种子都很好,只要它本身是半随机的。我见过的许多实现都使用 UNIX 纪元作为种子,它每秒都在变化,并且每次变化时都是独一无二的。
  • @user359996 rand()+rand() 不是均匀分布的。添加两个骰子,你更有可能得到 7 而不是 2。
  • @thenonhacker 在我的帖子中查看我对随机性的定义。仅仅因为值倾向于频谱的一端并不会增加所产生的确切值的可预测性,这就是我在使用随机这个词时所指的。然后我继续分别解决偏见问题。
【解决方案4】:

为了说明一个观点而过分简化。

假设您的随机函数仅输出 01

random()(0,1) 之一,但 random()*random()(0,0,0,1) 之一

您可以清楚地看到,在第二种情况下获得0 的机会绝不等于获得1 的机会。


当我第一次发布这个答案时,我希望它尽可能简短,以便阅读它的人一眼就能理解random()random()*random() 之间的区别,但我无法阻止自己回答原始广告问题:

哪个更随机?

random()random()*random()random()+random()(random()+1)/2 或任何其他不会导致固定结果的组合具有相同的熵源(或在伪随机的情况下具有相同的初始状态生成器),答案是它们是同样随机的(区别在于它们的分布)。我们可以看到的一个完美例子是掷骰子游戏。你得到的数字是random(1,6)+random(1,6),我们都知道得到 7 的机会最高,但这并不意味着掷两个骰子的结果比掷一个骰子的结果或多或少是随机的。

【讨论】:

  • +1 用于将非常棘手的东西浓缩为“在不同分布上同样随机”。非常优雅。
  • 从技术上讲,(random()*0+9) 是同样随机的,因为它从 1 元素集合中随机返回一个值:[9]。呆伯特卡通片是对的。
  • @Jens Rolan “任何其他不会导致固定结果的组合”;)。 999999 可能不是随机生成的,可以计算随机生成的概率。
【解决方案5】:

这是一个简单的答案。考虑垄断。你掷两个六面骰子(或者对于喜欢游戏符号的人来说是 2d6)并取它们的总和。最常见的结果是 7,因为有 6 种可能的方式可以掷出 7(1,6 2,5 3,4 4,3 5,2 和 6,1)。而 2 只能在 1,1 上滚动。很容易看出滚动 2d6 与滚动 1d12 不同,即使范围相同(忽略您可以在 1d12 上得到 1,点仍然相同)。将结果相乘而不是相加会以类似的方式使它们产生偏差,大多数结果都在范围的中间。如果你想减少异常值,这是一个好方法,但它无助于均匀分布。

(奇怪的是,它也会增加低掷骰。假设你的随机性从 0 开始,你会在 0 看到一个尖峰,因为它将把另一个掷骰子变成 0。考虑 0 到 0 之间的两个随机数1(含)和乘法。如果任一结果为 0,则无论其他结果如何,整个事物都变为 0。获得 1 的唯一方法是两个掷骰都为 1。在实践中,这可能会'没关系,但它会产生一个奇怪的图表。)

【讨论】:

  • “将结果相乘而不是相加会使它们以类似的方式倾斜,大多数结果都在范围的中间。” - 对照 belisarius 答案中的第二张图检查此断言。
【解决方案6】:

必填xkcd ...

【讨论】:

  • 该死的,当“随机出现”这个词时,它总是会出现:) 我在等它!!
  • 我喜欢幽默,但它必须是连续的。
  • @Andreas Rejbrand - 为什么这个“幽默”的答案应该是 CW?
  • 如果不是 CW,每次投票(到目前为止 160 个代表)时,声誉将被告知答案的发布者。现在,声誉就像学校的成绩——它应该是技术(在这种情况下是编程)熟练程度的证书。因此,一个人不应该通过发布一些容易被赞成但不需要这种熟练程度的东西来获得声誉。此外,信誉分数还决定了用户的权限。例如,得分为 10 000 时,用户可以访问 StackOverflow 上的审核工具。
【解决方案7】:

以更离散的数字考虑这一点可能会有所帮助。考虑要生成 1 到 36 之间的随机数,因此您决定最简单的方法是掷两个公平的 6 面骰子。你得到这个:

     1    2    3    4    5    6
  -----------------------------
1|   1    2    3    4    5    6
2|   2    4    6    8   10   12
3|   3    6    9   12   15   18
4|   4    8   12   16   20   24   
5|   5   10   15   20   25   30
6|   6   12   18   24   30   36

所以我们有 36 个数字,但并非所有数字都得到了公平的表示,有些根本没有出现。靠近中心对角线(左下角到右上角)的数字将出现频率最高。

描述骰子之间不公平分配的相同原则同样适用于 0.0 到 1.0 之间的浮点数。

【讨论】:

  • +1 用于更具体地显示乘以随机数时的分布变化。矩阵不仅有助于单词甚至是分布图。
【解决方案8】:

关于“随机性”的一些事情是违反直觉的。

假设rand() 的平坦分布,以下将为您提供非平坦分布:

  • 高偏差:sqrt(rand(range^2))
  • 偏差在中间达到峰值:(rand(range) + rand(range))/2
  • 低:偏差:range - sqrt(rand(range^2))

还有很多其他方法可以创建特定的偏差曲线。我对rand() * rand() 进行了快速测试,它得到了一个非常非线性的分布。

【讨论】:

    【解决方案9】:

    大多数 rand() 实现都有一段时间。 IE。在大量调用之后,序列重复。 rand() * rand() 的输出序列重复了一半的时间,因此在这个意义上它是“不那么随机的”。

    此外,如果没有仔细构造,对随机值执行算术往往会导致更少的随机性。上面的一张海报引用了“rand() + rand() + rand() ...”(例如 k 次),实际上这将趋向于 k 倍于 rand() 返回值范围的平均值。 (这是一个随机游走,步数与该均值对称。)

    假设你的 rand() 函数返回一个在 [0,1) 范围内均匀分布的随机实数。 (是的,这个例子允许无限精度。这不会改变结果。)您没有选择特定的语言,不同的语言可能会做不同的事情,但以下分析适用于任何非反常实现的 rand( )。乘积 rand() * rand() 也在 [0,1) 范围内,但不再均匀分布。事实上,产品在区间 [0,1/4) 中的可能性与在区间 [1/4,1) 中的可能性一样。更多的乘法会使结果更偏向于零。这使得结果更加可预测。概括地说,更可预测 == 更少随机性。

    几乎所有对均匀随机输入的操作序列都是非均匀随机的,从而提高了可预测性。小心,可以克服此属性,但这样会更容易在您实际想要的范围内生成均匀分布的随机数,而不是浪费时间进行算术运算。

    【讨论】:

    • 我也有过这样的想法,它会以两倍的速度经历随机生成器周期。
    • 序列长度只有在偶数时才会减半。如果是奇数,则得到 r1*r2, r3*r4, ..., rn*r1, r2*r3, r4*r5,总长度相同。
    【解决方案10】:

    “随机”与“更随机”有点像问哪个零更零。

    在这种情况下,rand 是一个 PRNG,所以不是完全随机的。 (事实上​​,如果种子是已知的,则完全可以预测)。将它乘以另一个值使其不再是随机的。

    真正的加密类型 RNG 实际上是随机的。并且通过任何类型的函数运行值都不能为其添加更多的熵,并且很可能会消除熵,使其不再随机。

    【讨论】:

    • 注意,这不是平方,因为每次调用都返回不同的值。其他一切都是准确的。
    • @thenonhacker:根据你自己的描述,序列“1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6 ,7,8,9,10,1,2,3,4,5,6,7,8,9,10..." 是随机的。它是均匀分布的,所有数字都有公平的机会。没有峰值或偏差。你真的认为这个序列是随机的???你需要改变你的定义。随机与输出无关,随机与用于创建输出的过程有关。
    • @CurtainDog:文本压缩保持熵水平不变,同时减少表达相同熵所需的位数。
    • @thenonhacker, @abelenky:即使是发行版也很容易。随机数生成器中重要的是随机数生成器状态中的位数。零状态随机数生成器(例如 4、4、4、4、4、...)是完全可预测的。 one-time-pad 的状态与其产生的值的数量一样多,因此无法预测。两个 PNRG 的卷积将产生一个 PNRG,其熵的位数与它们都包含的位数相同,减去它们的协方差。
    • @Kennet - 谢谢,你已经为我解决了这个问题。 @abelenky - 很酷,我现在明白了。
    【解决方案11】:

    您正在寻找的概念是“熵”,即字符串无序的“程度” 位。就“最大熵”的概念而言,这个想法最容易理解。

    具有最大熵的比特串的一个近似定义是它不能用较短的比特串来精确表达(即使用某种算法来 将较小的字符串展开回原来的字符串)。

    最大熵与随机性的相关性源于以下事实: 如果您“随机”选择一个数字,您几乎肯定会选择一个数字 其位串接近最大熵,即无法压缩。 这是我们对“随机”数字特征的最佳理解。

    因此,如果您想从两个随机样本中生成一个随机数,即“两倍”为 随机,您将连接这两个位串。实际上,您只需 将样本填充到双长字的高半部分和低半部分。

    更实际一点,如果您发现自己背负着一个糟糕的 rand(),它可以 有时有助于将几个样本异或在一起——尽管,如果它真的很差的话 该程序无济于事。

    【讨论】:

    • 我从来没有想过通过异或生成随机数,但我想你可以把这个概念走得很远(en.wikipedia.org/wiki/Mersenne_twister)!感谢您的回答。
    • 我真的很难理解这个答案......最大熵不是被stackoverflow.com/questions/3956478/understanding-randomness/…stackoverflow.com/questions/3956478/understanding-randomness/… 中给出的答案打败了。在这些情况下,选择的数字无法压缩,但您很难将它们随机命名。
    • +1 公认的答案很漂亮,这是我的最爱。谈到计算机时,请始终以位为单位进行思考 - 比尝试以实数思考更容易混淆和更相关。 (我写了我的答案,然后注意到了这个,所以我的只不过是这个的扩展——也许添加了一些熵)。
    • @CurtainDog xkcd 的随机数4 或二进制0100 可以压缩为零位。解压程序将简单地返回“4”。它不会比这更随机。 dilbert 的问题是,我们不知道是否可以将其压缩到零位(通过始终返回“九”来解压缩)。它也可能返回 8,然后我们可以压缩到 1 位。解压方式:0->9,1->8。我们会有 1 个随机位。
    【解决方案12】:

    接受的答案很可爱,但是还有另一种方法可以回答您的问题。 PachydermPuncher's answer 已经采用了这种替代方法,我只是将其扩展一点。

    考虑信息论的最简单方法是用最小的信息单位,一个比特。

    在 C 标准库中,rand() 返回一个介于 0 到 RAND_MAX 之间的整数,该限制可能会因平台而异。假设RAND_MAX 恰好被定义为2^n - 1,其中n 是某个整数(在Microsoft 的实现中恰好是这种情况,其中n 是15)。然后我们会说一个好的实现会返回n 位信息。

    想象rand() 构造随机数,方法是掷硬币找出一位的值,然后重复直到它有一批 15 位。然后位是独立的(任何一个位的值不影响同一批次中其他位具有一定值的可能性)。所以独立考虑的每个位就像一个介于 0 和 1 之间的随机数,并且在该范围内“均匀分布”(可能是 0 和 1)。

    位的独立性确保了位批次所代表的数字也将均匀分布在它们的范围内。这很直观:如果有 15 位,则允许的范围是零到 2^15 - 1 = 32767。该范围内的每个数字都是唯一的位模式,例如:

    010110101110010
    

    如果位是独立的,那么没有任何模式比任何其他模式更可能出现。因此,该范围内所有可能的数字都是同样可能的。所以反过来也是正确的:如果rand() 产生均匀分布的整数,那么这些数字是由独立的位组成的。

    因此,可以将rand() 视为制造比特的生产线,它恰好以任意大小的批次提供它们。如果您不喜欢大小,请将批次分成单独的位,然后以您喜欢的任意数量将它们重新组合在一起(尽管如果您需要一个不是 2 的幂的特定范围,则需要缩小数字,到目前为止,最简单的方法是转换为浮点数)。

    回到你原来的建议,假设你想从 15 个批次变成 30 个批次,向 rand() 询问第一个数字,将其位移 15 位,然后添加另一个 rand()。这是一种组合对rand() 的两次调用而不会影响均匀分布的方法。它之所以有效,是因为您放置信息位的位置之间没有重叠。

    这与通过乘以常数来“拉伸”rand() 的范围非常不同。例如,如果您想将rand() 的范围加倍,您可以乘以 2 - 但现在您只能得到偶数,而永远不会得到奇数!这并不是一个完全平滑的分布,并且可能是一个严重的问题,具体取决于应用程序,例如一个类似于轮盘赌的游戏,据说允许奇数/偶数下注。 (通过考虑位,您可以直观地避免该错误,因为您会意识到乘以 2 与将位向左(更大的意义)移动一位并用零填充间隙相同。所以很明显信息量是一样的——只是移动了一点。)

    在浮点数应用程序中无法解决数字范围中的这种差距,因为浮点范围本身就存在根本无法表示的差距:无限个缺失的实数每两个可表示的浮点数之间的间隙中存在数字!所以无论如何我们都必须学会忍受差距。

    正如其他人所警告的那样,直觉在这一领域是有风险的,尤其是因为数学家无法抗拒实数的诱惑,实数令人恐惧地混淆了充满粗糙无穷和明显悖论的事物。

    但至少如果你认为它是位的话,你的直觉可能会让你走得更远。位真的很容易 - 甚至 计算机 都能理解它们。

    【讨论】:

    • +1:实际上,任何两个 IEEE 双精度浮点数之间缺少的数字比整个(数学)整数中的数字还要多。
    【解决方案13】:

    正如其他人所说,简单的简短回答是:不,它不是更随机,但它确实改变了分布。

    假设您正在玩骰子游戏。你有一些完全公平的随机骰子。如果在每次掷骰之前先将两个骰子放入碗中,摇晃它,随机挑选一个骰子,然后再掷那个骰子,掷骰子会“更随机”吗?显然,这没有什么区别。如果两个骰子都给出随机数,那么随机选择两个骰子中的一个将没有区别。无论哪种方式,您都会得到一个介于 1 和 6 之间的随机数,并且在足够多的卷上均匀分布。

    我想在现实生活中,如果您怀疑骰子可能不公平,这样的程序可能会很有用。例如,如果骰子稍微不平衡,因此一个人倾向于给出 1 的频率高于 1/6,而另一个倾向于不寻常地给出 6,那么在两者之间随机选择往往会掩盖偏差。 (虽然在这种情况下,1 和 6 仍然会超过 2、3、4 和 5。嗯,我想这取决于不平衡的性质。)

    随机性有很多定义。随机序列的一个定义是它是由随机过程产生的一系列数字。根据这个定义,如果我掷一个公平的骰子 5 次并得到数字 2、4、3、2、5,那是一个随机序列。如果我再掷同一个公平骰子 5 次并得到 1、1、1、1、1,那么这也是一个随机系列。

    几位发帖人指出,计算机上的随机函数并不是真正随机的,而是伪随机的,如果你知道算法和种子,它们是完全可以预测的。这是真的,但大多数时候完全无关紧要。如果我洗一副牌,然后一次翻一张,这应该是一个随机系列。如果有人偷看牌,结果将是完全可以预测的,但根据大多数随机性的定义,这不会降低随机性。如果该系列通过了随机性的统计测试,我偷看卡片的事实不会改变这一事实。在实践中,如果我们在你猜下一张牌的能力上赌大笔钱,那么你偷看牌的事实是高度相关的。如果我们使用该系列来模拟我们网站访问者的菜单选择以测试系统的性能,那么您偷看的事实根本没有任何区别。 (只要您不修改程序以利用这些知识。)

    编辑

    我认为我无法将我对 Monty Hall 问题的回答变成评论,所以我会更新我的回答。

    对于那些没有阅读 Belisarius 链接的人来说,它的要点是:游戏节目参赛者可以选择 3 扇门。一个背后是有价值的奖品,另一个背后是毫无价值的东西。他选择 1 号门。在揭示它是赢家还是输家之前,主持人打开#3 门以表明它是输家。然后,他让参赛者有机会切换到 2 号门。参赛者是否应该这样做?

    出乎很多人直觉的答案是,他应该转行。他最初的选择是获胜者的概率是 1/3,另一扇门是获胜者的概率是 2/3。我和许多其他人的最初直觉是,切换不会有任何收获,赔率刚刚改为 50:50。

    毕竟,假设有人在主持人打开失败的门后打开了电视。那个人会看到剩下的两扇紧闭的门。假设他知道游戏的性质,他会说每扇门都有 1/2 的机会隐藏奖品。观众的赔率怎么可能是 1/2 : 1/2 而参赛者的赔率是 1/3 : 2/3?

    我真的不得不考虑这一点才能超越我的直觉。要掌握它,请了解当我们谈论此类问题中的概率时,我们的意思是,您在给定可用信息的情况下分配的概率。对于将奖品放在 1 号门后面的工作人员来说,奖品在 1 号门后面的概率是 100%,而在其他两个门后面的概率为零。

    机组成员的赔率与参赛者的赔率不同,因为他知道参赛者不知道的一些事情,即他将奖品放在哪扇门后面。同样,参赛者的赔率与观众的赔率不同,因为他知道观众不知道的一些事情,即他最初选择了哪扇门。这不是无关紧要的,因为主人选择打开哪扇门不是随机的。他不会打开参赛者选择的门,也不会打开隐藏奖品的门。如果这些是同一扇门,那他就有两个选择。如果它们是不同的门,那就只剩下一个。

    那么我们如何得出 1/3 和 2/3 呢?当参赛者最初选择一扇门时,他有 1/3 的机会选择获胜者。我认为这很明显。这意味着有 2/3 的机会其他门之一是赢家。如果主机游戏他有机会在不提供任何额外信息的情况下进行切换,那将没有任何收获。同样,这应该是显而易见的。但一种看待它的方式是说他有 2/3 的机会通过转换获胜。但他有两个选择。所以每个人只有 2/3 除以 2 = 1/3 的机会成为获胜者,这并不比他最初的选择好。当然我们已经知道了最终的结果,这只是计算方式不同而已。

    但现在主持人透露,这两个选择之一不是赢家。因此,他没有选择的门有 2/3 的机会是赢家,他现在知道 2 个备选方案中的 1 个不是它。另一个可能是也可能不是。所以他不再有 2/3 除以 2。他有 0 表示打开的门,2/3 表示关闭的门。

    【讨论】:

    • 很好的类比!我想这是一个非常好的简单的英语解释,与许多其他人不同,你实际上回答了我的问题:)
    • @Trufa @Jay 对事件的可能预知和随机性之间的混淆非常普遍。让我和你分享这个有趣的故事,关于一个女人解决了一个问题并给学院里一些更好的数学家蒙上了一层耻辱。他们说了很多事后后悔的话(比如“你犯了一个错误,但要看看积极的一面。如果那些博士都错了,国家就会陷入非常严重的困境。”)。所以这就是故事,与你的考虑有关……享受吧! marilynvossavant.com/articles/gameshow.html
    • @belisarius 是的。我说 blackjack21 :) 开个玩笑,我明白了!
    • @belisarius BTW 从来没有得到过那个,我现在再试一次!
    • @Trufa 这里有一篇文章展示了学术界对玛丽莲声明 query.nytimes.com/gst/… 的反应(非常非常有趣)
    【解决方案14】:

    假设您有一个简单的硬币翻转问题,其中偶数被视为正面,奇数被视为反面。逻辑实现是:

    rand() mod 2
    

    在足够大的分布上,偶数的个数应该等于奇数的个数。

    现在考虑稍微调整一下:

    rand() * rand() mod 2
    

    如果其中一个结果是偶数,那么整个结果应该是偶数。考虑 4 种可能的结果(偶数 * 偶数 = 偶数,偶数 * 奇数 = 偶数,奇数 * 偶数 = 偶数,奇数 * 奇数 = 奇数)。现在,在足够大的分布中,答案应该是 75% 的时间。

    如果我是你,我会打赌。

    这个评论实际上更多是解释为什么你不应该根据你的方法实现自定义随机函数,而不是讨论随机性的数学属性。

    【讨论】:

    • 当心! rand()%2 可能不是很随机;这实际上取决于低位的随机性,而某些 PRNG 并不是那么好。 (当然,在某些语言中,您会从 rand() 中得到浮点结果,因此您根本不能这样做……)
    【解决方案15】:

    当您对随机数组合会发生什么有疑问时,您可以使用您在统计理论中学到的课程。

    在 OP 的情况下,他想知道 X*X = X^2 的结果是什么,其中 X 是沿 Uniform[0,1] 分布的随机变量。我们将使用 CDF 技术,因为它只是一对一的映射。

    由于 X ~ Uniform[0,1] 它的 cdf 为:fX(x) = 1 我们想要转换 Y

    Y的分布如下: fY(y) = fX(x(y)) |dx/dy| = 1/(2 sqrt(y))

    我们还没有完成,我们必须得到 Y 的域。因为 0 Integrate 1/(2 sqrt(y)) from 0 to 1 并且确实弹出为 1。另外,请注意所述函数的形状看起来像 belisarious 发布的那样。

    至于 X1 + X2 + ... + Xn 之类的东西,(其中 Xi sub> ~ Uniform[0,1]) 我们可以求助于中心极限定理,它适用于任何存在矩的分布。这就是 Z 检验实际存在的原因。

    确定生成的 pdf 的其他技术包括雅可比变换(cdf 技术的通用版本)和 MGF 技术。

    编辑:作为澄清,请注意我说的是结果转换的分布,而不是它的随机性。这实际上是一个单独的讨论。我实际推导出的也是 (rand())^2。对于 rand() * rand() 它要复杂得多,在任何情况下都不会导致任何类型的均匀分布。

    【讨论】:

      【解决方案16】:

      这不是很明显,但rand() 通常比rand()*rand() 更随机。重要的是,这对于大多数用途而言实际上并不是很重要。

      但首先,它们产生不同的分布。 这不是问题,如果这是你想要的,但它确实很重要。如果你需要一个特定的分布,那么忽略整个“哪个更随机”的问题。那么为什么rand() 更随机呢?

      为什么rand() 更随机(假设它产生范围为 [0..1] 的浮点随机数,这很常见)的核心是当你将两个 FP 数相乘时尾数中有很多信息,最后你会丢失一些信息; IEEE 双精度浮点数中没有足够的位来保存从 [0..1] 中均匀随机选择的两个 IEEE 双精度浮点数中的所有信息,并且这些额外的信息位会丢失。当然,这并不重要,因为您(可能)不会使用该信息,但损失是真实的。您生成哪种发行版也并不重要(即,您使用哪种操作来进行组合)。这些随机数中的每一个(充其量)都具有 52 位的随机信息——这是 IEEE 双精度可以容纳的数量——如果将两个或多个组合成一个,你仍然被限制为最多具有 52 位的随机信息。

      大多数随机数的使用甚至没有使用随机源中实际可用的随机性。获得一个好的 PRNG,不要太担心它。 (“好”的程度取决于你用它做什么;在进行蒙特卡罗模拟或密码学时必须小心,否则你可能可以使用标准 PRNG,因为这通常更快。)

      【讨论】:

      • 这个答案真的需要结合贝利撒留的宏伟答案来阅读;它们涵盖了问题的不同方面。
      【解决方案17】:

      一般来说,浮动随机数基于一种算法,该算法产生一个介于零和特定范围之间的整数。因此,通过使用 rand()*rand(),您实际上是在说 int_rand()*int_rand()/rand_max^2 - 这意味着您排除了任何素数 / rand_max^2。

      这会显着改变随机分布。

      rand() 在大多数系统上是均匀分布的,如果正确播种,很难预测。除非您有特定的理由对其进行数学运算(即,将分布塑造成所需的曲线),否则请使用它。

      【讨论】:

      • @belisarius :只有当 1 是随机过程的可能结果时才会出现这种情况。
      • 在找到这个答案之前,我必须阅读很长的答案。您陈述了一个明确的问题:rand()*rand() 的结果空间(可能值的数量)小于rand() 的结果空间 - 因为它不包括素数。得到我的投票...
      【解决方案18】:

      根据您的计算机体系结构,乘数最终会在较小的解决方案范围内。

      如果您的计算机显示 16 位数字 rand() 会说 0.1234567890123 乘以第二个rand(),0.1234567890123,将得到 0.0152415 的东西 如果您将实验重复 10^14 次,您肯定会找到更少的解决方案。

      【讨论】:

        【解决方案19】:

        大多数分布的发生是因为您必须限制或规范化随机数。

        我们将其标准化为所有正数,适合某个范围,甚至适合分配的变量类型的内存大小限制。

        换句话说,因为我们必须将随机调用限制在 0 和 X 之间(X 是我们变量的大小限制),所以我们将有一组介于 0 和 X 之间的“随机”数字。

        现在,当您将随机数添加到另一个随机数时,总和将介于 0 和 2X 之间...这会使值偏离边缘点(将两个小数加在一起和两个大数加在一起的概率是当您在大范围内有两个随机数时非常小)。

        想想你有一个接近于零的数字,然后你将它与另一个随机数相加,它肯定会变得更大并且远离 0(这对于大数来说是正确的,而且不太可能有Random 函数两次返回的两个大数(接近 X 的数)。

        现在,如果您要使用负数和正数(在零轴上均等地跨越)设置随机方法,情况将不再如此。

        比如说RandomReal({-x, x}, 50000, .01),那么你会得到一个负数和正数的均匀分布,如果你将随机数加在一起,它们将保持它们的“随机性”。

        现在我不确定Random() * Random() 从负到正的跨度会发生什么......这将是一个有趣的图表......但我现在必须回到编写代码。 :-P

        【讨论】:

          【解决方案20】:
          1. 没有像更多随机这样的东西。它要么是随机的,要么不是随机的。随机意味着“难以预测”。这并不意味着非确定性。如果 random() 是随机的,则 random() 和 random() * random() 都是同样随机的。就随机性而言,分布是无关紧要的。如果出现非均匀分布,则仅意味着某些值比其他值更有可能;它们仍然是不可预测的。

          2. 由于涉及到伪随机性,因此这些数字非常具有确定性。然而,在概率模型和模拟中,伪随机性通常就足够了。众所周知,使伪随机数生成器变得复杂只会使其难以分析。不太可能改善随机性;它经常导致它无法通过统计测试。

          3. 所需的随机数属性很重要:可重复性和再现性、统计随机性、(通常)均匀分布和大周期。

          4. 关于随机数的转换:正如有人所说,两个或多个均匀分布的总和导致正态分布。这就是加法中心极限定理。只要所有分布都是独立且相同的,它就适用于任何源分布。 乘法中心极限定理说两个或多个独立且一致分布的随机变量的乘积是对数正态的。其他人创建的图表看起来是指数的,但它实际上是对数正态的。所以 random() * random() 是对数正态分布的(尽管它可能不是独立的,因为数字是从同一个流中提取的)。这在某些应用中可能是合乎需要的。但是,通常最好生成一个随机数并将其转换为对数正态分布的数。 Random() * random() 可能很难分析。

          有关更多信息,请参阅我在 www.performorama.org 上的书。这本书正在编写中,但相关的材料在那里。请注意,章节编号可能会随时间而变化。第 8 章(概率论)——第 8.3.1 和 8.3.3 节,第 10 章(随机数)。

          【讨论】:

            【解决方案21】:

            我们可以通过使用来比较两个关于随机性的数字数组 Kolmogorov complexity 如果数字序列不能被压缩,那么它是我们在这个长度上可以达到的最随机的...... 我知道这种类型的测量更多是一种理论上的选择......

            【讨论】:

              【解决方案22】:

              实际上,rand() * rand()rand() 随机性。原因如下。

              基本上,奇数的数量与偶数的数量相同。并且说 0.04325 是奇数,就像 0.388 是偶数,而 0.4 是偶数,而 0.15 是奇数,

              这意味着rand()成为偶数或奇数小数的机会均等

              另一方面,rand() * rand() 的赔率有点不同。 让我们说:

              double a = rand();
              double b = rand();
              double c = a * b;
              

              ab 都有 50% 的几率是偶数或奇数。知道了

              • 偶数 * 偶数 = 偶数
              • 偶数 * 奇数 = 偶数
              • 奇数 * 奇数 = 奇数
              • 奇数 * 偶数 = 偶数

              表示c75% 的机会 是偶数,而只有 25% 的机会 是奇数,这使得 rand() * rand() 的值比rand(),因此随机性较小。

              【讨论】:

              • rand() 通常给出一个介于 0 和 1 之间的数字。谈论它是偶数还是奇数有意义吗?
              • 实际上,0.2*0.2=0.04,这表明这种方法存在一个根本缺陷:将两个双精度数的 53 位相乘将得到大约 100 位的结果。但是这些位的后半部分将被丢弃。因此,当你取两个双精度数时,它们的最低有效位为 1,你不能说他们乘积的最低有效位。
              • 或者,换一种说法,你假设对rand()的分布有意义的“偶数”和“奇数”的定义与“偶数”的定义相同" 和 "odd" 对rand()*rand() 的分布有意义。如果不是这样,这个论点就失败了。整数确实如此,但它们不是整数。
              【解决方案23】:

              使用实现原始多项式的线性反馈移位寄存器 (LFSR)。

              结果将是一个由 2^n 个伪随机数组成的序列,即没有在序列中重复,其中 n 是 LFSR 中的位数 .... 导致均匀分布。

              http://en.wikipedia.org/wiki/Linear_feedback_shift_register http://www.xilinx.com/support/documentation/application_notes/xapp052.pdf

              使用基于计算机时钟微秒的“随机”种子,或者可能是文件系统中某些不断变化的数据的 md5 结果的子集。

              例如,32 位 LFSR 将从给定种子开始按顺序生成 2^32 个唯一数字(没有 2 个类似数字)。 序列将始终保持相同的顺序,但对于不同的种子,起点将不同(显然)。 因此,如果种子之间的可能重复序列不是问题,这可能是一个不错的选择。

              我使用 128 位 LFSR 在硬件模拟器中生成随机测试,使用种子是不断变化的系统数据的 md5 结果。

              【讨论】:

                【解决方案24】:

                假设rand()返回一个介于[0, 1)之间的数字,很明显rand() * rand()会偏向0。这是因为将x乘以[0, 1)之间的数字会得到一个小于@的数字987654326@。这是 10000 更多个随机数的分布:

                google.charts.load("current", { packages: ["corechart"] });
                google.charts.setOnLoadCallback(drawChart);
                
                function drawChart() {
                  var i;
                  var randomNumbers = [];
                  for (i = 0; i < 10000; i++) {
                    randomNumbers.push(Math.random() * Math.random());
                  }
                  var chart = new google.visualization.Histogram(document.getElementById("chart-1"));
                  var data = new google.visualization.DataTable();
                  data.addColumn("number", "Value");
                  randomNumbers.forEach(function(randomNumber) {
                    data.addRow([randomNumber]);
                  });
                  chart.draw(data, {
                    title: randomNumbers.length + " rand() * rand() values between [0, 1)",
                    legend: { position: "none" }
                  });
                }
                <script src="https://www.gstatic.com/charts/loader.js"></script>
                
                <div id="chart-1" style="height: 500px">Generating chart...</div>

                如果rand() 返回一个介于[x, y] 之间的整数,那么您有以下分布。注意奇数和偶数的数量:

                google.charts.load("current", { packages: ["corechart"] });
                google.charts.setOnLoadCallback(drawChart);
                document.querySelector("#draw-chart").addEventListener("click", drawChart);
                
                function randomInt(min, max) {
                  return Math.floor(Math.random() * (max - min + 1)) + min;
                }
                
                function drawChart() {
                  var min = Number(document.querySelector("#rand-min").value);
                  var max = Number(document.querySelector("#rand-max").value);
                  if (min >= max) {
                    return;
                  }
                  var i;
                  var randomNumbers = [];
                  for (i = 0; i < 10000; i++) {
                    randomNumbers.push(randomInt(min, max) * randomInt(min, max));
                  }
                  var chart = new google.visualization.Histogram(document.getElementById("chart-1"));
                  var data = new google.visualization.DataTable();
                  data.addColumn("number", "Value");
                  randomNumbers.forEach(function(randomNumber) {
                    data.addRow([randomNumber]);
                  });
                  chart.draw(data, {
                    title: randomNumbers.length + " rand() * rand() values between [" + min + ", " + max + "]",
                    legend: { position: "none" },
                    histogram: { bucketSize: 1 }
                  });
                }
                <script src="https://www.gstatic.com/charts/loader.js"></script>
                
                <input type="number" id="rand-min" value="0" min="0" max="10">
                <input type="number" id="rand-max" value="9" min="0" max="10">
                <input type="button" id="draw-chart" value="Apply">
                
                <div id="chart-1" style="height: 500px">Generating chart...</div>

                【讨论】:

                  【解决方案25】:

                  好的,所以我会尝试通过说您正在创建和使用随机数生成器来添加一些价值来补充其他答案。

                  随机数生成器是具有多种特性的设备(在非常一般的意义上),可以对其进行修改以适应目的。其中一些(来自我)是:

                  • 熵:如香农熵
                  • 分布:统计分布(泊松、正态等)
                  • 类型:数字的来源(算法、自然事件、组合等)和应用的算法。
                  • 效率:执行的速度或复杂性。
                  • 模式:周期性、序列、运行等。
                  • 可能还有更多...

                  在这里的大多数答案中,分布是主要的兴趣点,但是通过混合和匹配函数和参数,您可以创建新的随机数生成方法,这些随机数将具有不同的特征,其中一些评估起初可能并不明显一目了然。

                  【讨论】:

                    【解决方案26】:

                    很容易证明两个随机数之和不一定是随机的。想象一下,你有一个 6 面的骰子和掷骰子。每个数字有 1/6 的机会出现。现在假设你有 2 个骰子并将结果相加。这些总和的分布不是 1/12。为什么?因为某些数字比其他数字出现得更多。其中有多个partitions。例如数字 2 只是 1+1 的和,但 7 可以由 3+4 或 4+3 或 5+2 等组成……所以它出现的机会更大。

                    因此,应用变换,在这种情况下,对随机函数进行加法并不会使它更加随机,或者必然保持随机性。在上述骰子的情况下,分布偏斜为 7,因此随机性较小。

                    【讨论】:

                      【解决方案27】:

                      正如其他人已经指出的那样,这个问题很难回答,因为我们每个人的脑海中都有自己的随机性图景

                      这就是为什么,我强烈建议您花一些时间阅读本网站,以更好地了解随机性:

                      回到真正的问题。 这个词没有或多或少的随机性:

                      两者都只是随机出现

                      在这两种情况下 - 只是 rand() 或 rand() * rand() - 情况是一样的: 在几十亿个数字之后,序列将重复(!)。 它在观察者看来是随机的,因为他不知道整个序列,但是计算机没有真正的随机源 - 所以他不能也产生随机性。

                      例如:天气是随机的吗? 我们没有足够的传感器或知识来确定天气是否随机。

                      【讨论】:

                        【解决方案28】:

                        答案取决于情况,希望 rand()*rand() 会比 rand() 更随机,但如下:

                        • 这两个答案都取决于您的值的位数
                        • 在大多数情况下,您生成取决于伪随机算法(主要是取决于您的计算机时钟的数字生成器,而不是那么随机)。
                        • 让您的代码更具可读性(而不是用这种咒语调用一些随机的巫毒神)。

                        好吧,如果您检查以上任何一项,我建议您选择简单的“rand()”。 因为你的代码会更可读(不会问自己为什么写这个,因为......嗯......超过 2 秒),易于维护(如果你想替换你rand 函数与 super_rand)。

                        如果您想要更好的随机,我建议您从任何提供足够噪音的来源(无线电静态)流式传输它,然后一个简单的rand() 就足够了。

                        【讨论】:

                          猜你喜欢
                          • 1970-01-01
                          • 1970-01-01
                          • 1970-01-01
                          • 2019-02-26
                          • 2019-09-19
                          • 1970-01-01
                          • 1970-01-01
                          • 1970-01-01
                          • 1970-01-01
                          相关资源
                          最近更新 更多