我无法理解这个,哪个更随机?
rand()
OR:
rand() * rand()
我发现这是一个真正的脑筋急转弯,你能帮我吗?
编辑:
直觉上,我知道数学上的答案是它们是同样随机的,但我不禁想,如果你在将两者相乘时“运行随机数算法”两次,你会创建比只做一次更随机的东西。
我无法理解这个,哪个更随机?
rand()
OR:
rand() * rand()
我发现这是一个真正的脑筋急转弯,你能帮我吗?
编辑:
直觉上,我知道数学上的答案是它们是同样随机的,但我不禁想,如果你在将两者相乘时“运行随机数算法”两次,你会创建比只做一次更随机的东西。
当前回答
根据您的计算机体系结构,相乘数字最终会得到更小的解决方案范围。
如果您的计算机显示16位数字,rand()将为0.1234567890123乘以第二个rand(),0.1234567890123,将得到0.0152415如果你把实验重复10^14次,你肯定会找到更少的解决方案。
其他回答
答案将是,这取决于,希望rand()*rand(()比rand)更随机,但如下所示:
两个答案都取决于你的值的位数在大多数情况下,你根据伪随机算法生成(它主要是一个数字生成器,依赖于你的计算机时钟,而不是那么随机)。让你的代码更可读(不要用这种咒语来召唤一些随机的巫毒神)。
好吧,如果你检查上面的任何一个,我建议你使用简单的“rand()”。因为你的代码会更可读(不会问自己为什么要写这个,时间……嗯……超过2秒),易于维护(如果你想用super_rand替换rand函数)。
如果你想要更好的随机性,我建议你从任何提供足够噪声的源(无线电静态)流式传输,然后一个简单的rand()就足够了。
“随机”与“更随机”有点像问哪个零更为零。
在这种情况下,rand是PRNG,所以不是完全随机的。(事实上,如果种子是已知的,那是完全可以预测的)。将其乘以另一个值,使其不再随机。
真正的加密类型RNG实际上是随机的。通过任何类型的函数运行值都不能增加更多的熵,而且很可能会删除熵,使其不再随机。
没有比这更随机的了。它要么是随机的,要么不是随机的。随机意味着“难以预测”。这并不意味着不确定性。如果random()是随机的,那么random(()和random(*random)都是随机的。就随机性而言,分布是无关紧要的。如果出现不均匀分布,则意味着某些值比其他值更有可能;它们仍然是不可预测的。由于涉及伪随机性,所以这些数字非常具有确定性。然而,在概率模型和模拟中,伪随机性通常是足够的。众所周知,使伪随机数生成器复杂化只会使其难以分析。不太可能提高随机性;它经常导致它无法通过统计测试。随机数的期望财产很重要:重复性和再现性、统计随机性、(通常)均匀分布和大周期是少数几个。关于随机数上的变换:正如有人所说,两个或多个均匀分布的和产生正态分布。这是加法中心极限定理。无论源分布如何,只要所有分布都是独立和相同的,它都适用。乘性中心极限定理表示两个或多个独立且一致分布的随机变量的乘积是对数正态的。其他人创建的图形看起来是指数型的,但实际上是对数正态的。因此random()*random(()是对数正态分布的(尽管它可能不是独立的,因为数字是从同一个流中提取的)。这在某些应用中可能是期望的。然而,通常最好生成一个随机数并将其转换为对数正态分布数。Random()*Random()可能很难分析。
欲了解更多信息,请访问www.performorama.org查阅我的书。这本书正在建设中,但相关材料已经存在。请注意,章节和章节编号可能会随时间而变化。第8章(概率论)——第8.3.1和8.3.3节,第10章(随机数)。
这不是很明显,但rand()通常比rand(*rand)更随机。重要的是,对于大多数用途来说,这实际上不是很重要。
但首先,它们产生了不同的分布。如果这是你想要的,这不是问题,但这很重要。如果你需要一个特定的分布,那么忽略整个“哪个更随机”的问题。那么为什么rand()更随机呢?
rand()之所以更随机(假设它产生的是[0..1]范围内的浮点随机数,这是非常常见的)的核心是,当你将两个FP数与尾数中的大量信息相乘时,你会在结尾处丢失一些信息;IEEE双精度浮点中没有足够的位来保存从[0..1]中均匀随机选择的两个IEEE双精度浮点数中的所有信息,这些额外的信息位将丢失。当然,这无关紧要,因为你(可能)不会使用这些信息,但损失是真实的。您产生哪种分布(即,使用哪种操作进行组合)也并不重要。这些随机数中的每一个都有(最多)52位随机信息——这就是IEEE双精度的容量——如果你将两个或多个随机数合并为一个,那么你仍然只能拥有最多52位的随机信息。
大多数随机数的使用甚至没有使用随机源中实际可用的那么多随机性。得到一个好的PRNG,不要太担心它。(“好”的程度取决于你在用它做什么;你在做蒙特卡洛模拟或密码学时必须小心,否则你可能会使用标准PRNG,因为这通常要快得多。)
公认的答案很好,但有另一种方法可以回答你的问题。PachydermPuncher的答案已经采用了这种替代方法,我只是将其扩展一点。
思考信息理论最简单的方法是用最小的信息单位,一个比特。
在C标准库中,rand()返回一个0到rand_MAX范围内的整数,根据平台的不同,这个限制可能会有不同的定义。假设RAND_MAX恰好被定义为2^n-1,其中n是某个整数(这恰好是Microsoft实现中的情况,其中n为15)。然后我们可以说,一个好的实现将返回n位信息。
想象一下,rand()通过翻转硬币找到一位的值来构造随机数,然后重复直到它有一批15位。然后,这些位是独立的(任何一个位的值都不会影响同一批中其他位具有特定值的可能性)。因此,独立考虑的每个比特都像一个介于0和1之间的随机数,并且在该范围内“均匀分布”(可能是0和1)。
位的独立性确保了由一批位表示的数字也将在其范围内均匀分布。这很明显:如果有15位,允许的范围是0到2^15-1=32767。该范围内的每个数字都是唯一的位模式,例如:
010110101110010
并且如果比特是独立的,则没有模式比任何其他模式更可能发生。因此,该范围内所有可能的数字都有相同的可能性。反之亦然:如果rand()产生均匀分布的整数,那么这些数字是由独立的位组成的。
因此,将rand()看作是一条生产比特的生产线,它恰好以任意大小的批量提供比特。如果您不喜欢大小,请将批分成单独的位,然后按您喜欢的数量将它们放回一起(尽管如果您需要的特定范围不是2的幂,则需要缩小数字,目前最简单的方法是转换为浮点)。
回到你最初的建议,假设你想从15个批次到30个批次,向rand()请求第一个数字,将其移位15位,然后向其添加另一个rand(()。这是一种在不影响均匀分布的情况下组合对rand(的两个调用的方法。它的工作原理很简单,因为放置信息位的位置之间没有重叠。
这与通过乘以常数来“拉伸”rand()的范围非常不同。例如,如果你想将rand()的范围加倍,你可以乘以2,但现在你只能得到偶数,而不能得到奇数!这并不完全是一个平稳的分布,并且可能是一个严重的问题,具体取决于应用程序,例如,假设允许奇数/偶数下注的轮盘游戏。(从位的角度考虑,你可以直观地避免这个错误,因为你会意识到,乘以2等于将位向左移动一位(意义更大),然后用零填补空白。所以很明显,信息量是一样的——只是移动了一点。)
在浮点数应用程序中,数字范围中的这种差距是无法解决的,因为浮点数范围内在地具有根本无法表示的差距:在每两个可表示的浮点数之间的差距中存在无限数量的缺失实数!所以无论如何,我们必须学会与差距共处。
正如其他人所警告的那样,直觉在这一领域是有风险的,特别是因为数学家无法抵抗实数的诱惑,因为实数是一种充满了粗糙的无限和明显的悖论的可怕的令人困惑的东西。
但至少如果你从比特角度来看,你的直觉可能会让你走得更远。比特真的很容易——甚至计算机都能理解。