【问题标题】:How to Make a Uniform Random Integer Generator from a Random Boolean Generator?如何从随机布尔生成器制作统一的随机整数生成器?
【发布时间】:2020-03-09 03:57:59
【问题描述】:

我有一个基于硬件的布尔生成器,可以统一生成 1 或 0。如何使用它来制作一个统一的 8 位整数生成器?我目前正在使用收集的布尔值来为 8 位整数创建二进制字符串。生成的整数不是均匀分布的。它遵循this page 上解释的分布。具有 ̶a̶ ̶l̶o̶t̶ ̶o̶f̶ ̶a̶l̶t̶e̶r̶n̶a̶t̶I̶n̶g̶ ̶b̶I̶t̶s̶ 的整数具有相同数量的 1 和 0,例如 85 (01010101) 和 -86 (10101010) 最有可能生成,具有大量重复位的整数,例如 0 (000000) (11111111) 的机会最低。

这是我用每个可能的 4 位整数的概率注释的页面。我们可以看到它们并不统一。具有相同数量的 1 和 0 的 3、5、6、-7、-6 和 -4 具有 ⁶/₁₆ 概率,而所有位相同的 0 和 -1 仅具有 ¹/₁₆ 概率。

这里是my implementation on Kotlin

【问题讨论】:

  • 我建议将该信息编辑到您的问题中。好问题。
  • 如果您的位源有偏差,那么您需要研究一种去偏技术。 RFC 4086 给出了一些建议。冯诺依曼技术(参见 RFC 的 4.2 节)很简单,尽管还有其他方法。在某种程度上,您必须使去偏技术适合您的位源的特定偏差。
  • @rossum 它的香农熵是 0.99916596。它通过了所有 114 项更顽固的测试。其中之一被认为是弱者。您认为哪种纠偏方法最适合我的情况?
  • 这是一个有趣的问题,但描述仍然不清楚。您应该明确说明如何从位构造整数。您还应该具体说明生成的整数的分布——链接到的页面上有很多东西,所以期望其他人试图弄清楚您可能在谈论哪几件事是不合理的。
  • @RobertDodier 对不起。我已经注释了页面。我希望现在更清楚一点

标签: kotlin random probability probability-theory


【解决方案1】:

根据您的编辑,这里似乎存在误解。通过“统一 4 位整数”,您似乎有以下想法:

  1. 从 0 开始。
  2. 生成一个随机位。如果是 1,则加 1,否则减 1。
  3. 再重复步骤 2 三次。
  4. 输出结果数。

虽然随机位生成器可能会生成每个结果与另一个结果一样可能随机生成的位,并且每个 4 位块可能与任何其他块一样可能随机生成,但每个结果中的位数块不是均匀分布的。

你想要什么范围的整数?假设您正在生成 4 位整数。你想要一个 [-4, 4] 的范围,就像你问题中的 4 位随机游走一样,还是你想要一个 [-8, 7] 的范围,这是你处理 4-位块作为二进制补码整数?

如果是前者,随机游走不会产生均匀分布,您需要以不同的方式解决问题。

在这种情况下,要在 [-4, 4] 范围内生成一个统一的随机数,请执行以下操作:

  1. 取随机位生成器的 4 位,并将其视为 [0, 15) 中的整数;
  2. 如果整数大于 8,则转到步骤 1。
  3. 从整数中减去 4 并输出。

该算法使用拒绝采样,但它是可变时间的(因此在安全攻击中可以利用时间差异时不适合)。其他范围的数字也是类似生成的,但细节过于复杂,无法在此答案中描述。有关详细信息,请参阅我在random number generation methods 上的文章。


根据您向我展示的代码,您构建bytes、ints 和longs 的方法很容易出错。例如,构建一个 8 位字节以实现您想要的更好的方法如下(请记住,我对 Kotlin 不是很熟悉,所以语法可能是错误的):

val i = 0
val b = 0
for (i = 0; i < 8; i++) {
   b = b << 1; // Shift old bits
   if (bitStringBuilder[i] == '1') {
      b = b | 1; // Set new bit
   } else {
      b = b | 0; // Don't set new bit
   }
}
value = (b as byte) as T

此外,如果MediatorLiveData 不是线程安全的,那么您使用StringBuilder 收集位的方法也不是线程安全的(尤其是因为StringBuilder 不是线程安全的)。


您建议的方法将布尔生成器的八位组合成一个统一的整数,理论上可行。但是,在实践中存在几个问题:

  • 你没有提到它是什么类型的硬件。在大多数情况下,除非硬件是为此目的而设计的所谓的真随机数生成器,否则硬件不太可能生成均匀随机的布尔位。例如,硬件可能会生成均匀分布的位,但具有周期性行为。
  • 表示与理想随机值相比,预测生成器产生的值的难度。例如,具有 32 位熵的 64 位数据块与理想的随机 32 位数据块一样难以预测。表征硬件设备的熵(或产生不可预测值的能力)绝非易事。除其他外,这涉及必须在适用于硬件的所有操作条件(例如温度、电压)范围内进行的熵测试。
  • 大多数硬件无法产生统一的随机值,因此通常需要一个额外的步骤,称为随机提取熵提取无偏白化,或去歪斜,用于将硬件生成的值转换为均匀分布的随机数。但是,如果首先表征硬件的熵,则效果最好(参见上一点)。
  • 最后,您还必须测试整个过程是否会为您的目的提供“足够随机”的数字。有几个统计测试试图这样做,例如 NIST 的统计测试套件或 TestU01。

有关详细信息,请参阅“Nondeterministic Sources and Seed Generation”。


在您编辑此页面后,您似乎以错误的方式解决问题。为了产生一个统一的随机数,您不要添加均匀分布的随机位(例如,bit() + bit() + bit()),而是连接它们(例如,(bit() &lt;&lt; 2) | (bit() &lt;&lt; 1) | bit())。然而,由于我上面提到的原因,这在理论上是可行的,但在实践中是行不通的。

【讨论】:

  • 是的,我连接了这些位而不是添加它们。随机性是从我手机摄像头上一个像素的散粒噪声中收集的,所以从技术上讲,它是一个量子 RNG。它的香农熵是 0.99916596。它还通过了所有 114 项更顽固的测试。其中之一被认为是弱者。我不确定我的方法是否足够好,因为某些数字的生成频率高于其他数字。如果我生成标准的 32 位整数,则永远不会生成 0 和 1,因为我的布尔生成器永远不会重复生成相同的位 32 次。你建议什么样的公正方法?
  • 对于随机数生成目的,min-entropy 比 Shannon entropy 更合适。此外,还有许多可用的无偏技术:von Neumann、HMAC-SHA512 等。 (例如,Cliff/Boyd/Gonzalez 在 2009 年将 HMAC 视为随机提取器。)还要注意,尽管底层比特生成器可能是均匀的,但来自该生成器的随机游走分布远非均匀。
  • 这就是我要解决的问题。有没有办法让比特生成器的随机游走分布更均匀?不偏不倚能解决这个问题吗?我可以将生成的整数作为 PRNG 的种子。随机游走分布应该更均匀。但我不确定这是否是个好主意,因为生成的数字会更容易预测
  • 您链接到的页面上写着:“如果是正面,则向前迈出一步。如果是反面,则向后退一步。”换句话说:“如果位为0,则加1。如果位为1,则减1。”您从 0 开始,然后根据 8 位中每一位的结果加或减 1,然后返回结果。这个数字的范围可以从 -8 到 8。这远非均匀分布。 (如果这不是您的意思,请编辑您的问题并详细说明您是如何使用比特生成器形成随机数的、您得到的结果(带有示例)以及您期望的结果。)
  • 另一方面,您似乎想要的“均匀随机游走”也称为“白噪声”。对于这种遍历,只需从随机位生成器中取出 8 位块,并将它们中的每一个视为 8 位整数的二进制补码形式。
猜你喜欢
  • 2014-10-17
  • 1970-01-01
  • 2011-09-18
  • 1970-01-01
  • 1970-01-01
  • 2023-01-03
  • 1970-01-01
  • 2017-09-05
相关资源
最近更新 更多