【问题标题】:Generate very very large random numbers生成非常非常大的随机数
【发布时间】:2011-07-23 19:06:29
【问题描述】:

如何生成一个非常大的随机数?我正在考虑 2^10^9(十亿位)的数量级。任何编程语言——我认为解决方案会翻译成其他语言。

我想要 [1,N] 上的均匀分布。

我最初的想法:

--您可以随机生成每个数字并连接。问题:即使是非常好的伪随机生成器也可能产生数百万位数的模式,对吧?

  • 您也许可以通过将随机数提高到随机指数来帮助创建大随机数。问题:您必须进行数学运算,以使结果数字仍然是随机的,并且您应该能够在合理的时间内(例如,一个小时)计算它。

  • 如果有帮助,您可以尝试在可能更小的范围内生成可能不均匀的分布(例如,使用实数)并进行变换。问题:这可能同样困难。

有什么想法吗?

【问题讨论】:

  • 你打算把它存储在哪种类型中?
  • 你需要这个号码做什么?
  • 猜猜它必须是一个字符串,或者可能是写入磁盘的纯二进制数据......欢迎提出建议!
  • 主要是为了尝试/为了好玩。我在一个可能有用的数论课上。当然,我没有与可证明的数字随机性有关的重要数据。
  • 小心。 “可证明随机”是一个非常棘手的概念。任何典型的 RNG 都不会这样做。

标签: math random number-theory


【解决方案1】:

这取决于您需要数据的目的。对于大多数目的,PRNG 快速而简单。但它们并不完美。例如,我记得听说过混沌系统的蒙特卡洛斯模拟非常擅长揭示 PRNG 中的潜在模式。

不过,如果这是您正在做的事情,那么我在研究生院学到了一个简单的技巧来生成大量随机数据。拿一个大的(最好是快速变化的)文件。 (运行内核的一些大数据结构很好。)压缩它以增加熵。扔掉标题。然后为了好的措施,加密结果。如果您打算将其用于加密目的(并且您没有完美的熵数据集可供使用),则将其反转并再次加密。

基本理论很简单。信息论告诉我们,没有冗余的信号和纯随机数据之间没有区别。因此,如果我们选择一个大文件(即大量信号),通过压缩去除冗余,并剥离标题,我们就会得到一个非常好的随机信号。加密在消除伪影方面做得非常好。然而,加密算法倾向于以块的形式进行。因此,如果有人能不顾一切地猜出文件开头发生了什么,那么该数据就更容易被猜到。但随后反转文件并再次加密意味着他们需要知道整个文件和我们的加密,才能找到数据中的任何模式。

选择快速变化的数据的原因是,如果您用完了数据并想要生成更多数据,您可以再次返回相同的来源。在这个过程之后,即使是很小的变化也会变成一个本质上不相关的随机数据集。

【讨论】:

    【解决方案2】:

    即使是非常好的伪随机生成器也可能产生数百万位数的模式,对吧?

    来自the wikipedia on pseudo-random number generation

    可以使用种子状态从任意起始状态启动 PRNG。此后,当使用该状态初始化时,它将始终产生相同的序列。序列开始重复之前的最大长度由状态的大小决定,以比特为单位。但是,由于添加“状态”的每一位,最大周期的长度可能会加倍,因此很容易构建周期足够长的 PRNG,以用于许多实际应用。

    您也许可以通过将随机数提高到随机指数来帮助创建大随机数

    我假设您建议使用随机值填充科学计数法的值?

    例如:1.58901231 x 10^5819203489

    这样做的问题是您的分布将是对数的(或者是指数的?:) - 相同的差异,它不是偶数)。你永远不会得到一个包含第百万位数字集的值,但在一个列中包含一个数字。

    您可以尝试在可能更小的范围内生成可能不均匀的分布(例如,使用实数)并进行变换

    不确定我是否理解这一点。听起来与指数解决方案相同,但问题相同。如果你说的是乘以一个常数,那么你会得到一个块状分布,而不是对数(指数?)分布。

    建议的解决方案

    如果您只需要具有良好分布的非常大的伪随机值,请使用具有更大状态的 PRNG 算法。 PRNG 的周期性通常是位数的平方,因此即使是非常大的数字也不需要 那么 很多位。

    从那里,您可以使用您的第一个解决方案:

    您可以随机生成每个数字并连接

    尽管我建议您使用 PRNG 返回的所有值(可能是 2^31 或 2^32),并用这些值填充一个字节数组,并根据需要将其拆分。否则你可能会丢掉很多随机性。此外,将您的值缩放到一个范围(或使用模数)很容易搞砸您的分布,因此尝试保持 PRNG 可以返回的最大位数还有另一个原因。但是,请小心将返回的位包含在您的字节数组中,否则您将再次在您的分布中引入块状。

    但是,这些解决方案的问题是如何用足够随机的值填充(大于正常的)种子状态。您可能能够使用标准大小的种子(通过时间或 GUID 样式的人口填充),并使用来自较小 PRNG 的值填充您的大 PRNG 状态。如果您的数字分布的好坏不是关键任务,这可能会起作用。

    如果您需要真正加密安全的随机值,唯一真正的方法是使用自然形式的随机性,例如http://www.random.org/。自然随机性的缺点是可用性,而且许多自然随机设备需要一段时间才能生成新的熵,因此生成大量数据可能真的很慢。

    您也可以使用混合种子并确保安全 - 仅使用自然随机种子(以避免生成缓慢),其余部分使用 PRNG。定期重新播种。

    【讨论】:

      【解决方案3】:

      NTL: A Library for doing Number Theory

      这是我的编码理论和密码学老师推荐的……所以我想它做得对,而且很容易使用。

      RandomBnd、RandomBits、RandomLen -- 生成伪随机数的例程

      ZZ RandomLen_ZZ(long l);
      // ZZ = psuedo-random number with precisely l bits,
      // or 0 of l <= 0.
      

      【讨论】:

      • 看起来很有趣,但我无法从文档中判断它是否可以满足我的要求。你知道吗?
      • 我用它来实现 RSA 密码......但我想我已经丢失了源代码......而且很久以前我都不记得我在那里做了什么......
      • 啊。感谢您的链接——总的来说可能真的很有用。但从源头看来,这些不适用于非常大的数字。
      【解决方案4】:

      生成log2(N)随机位得到一个数字M, 其中M 可能是N 的两倍。 重复直到M[1;N] 范围内。

      现在要生成随机位,您可以使用真正的随机源,这很昂贵。

      或者您可能会使用一些加密安全的随机数生成器,例如带有随机密钥的 AES,用于加密后续位块的计数器。加密安全意味着不会有明显的模式。

      【讨论】:

      • 2 个问题。 1)是否有一个简单的证明可以证明 k 个随机位产生一个随机的 k 位数?看起来很直观,但是.... 2) 加密安全听起来不错——这意味着它与随机数无法区分,对吗?所以你建议,让 k 是一个 128 位随机密钥,然后对于 b=1 到 log2(N)/128,使用 k 将 b 加密为某个 128 位数字并将该数字连接起来。是吗?
      • 我不明白您将如何使用 AES 生成随机数。您是否暗示 AES 生成的密文没有明显的模式,通过这种方式,我们可以将其用作随机数?
      • 这似乎相当浪费,因为在最坏的情况下(N 刚刚超过 2 的幂),您最终会丢掉将近一半的尝试!
      • 确实如此,但这是纯面向位方法的结果。为了减轻这种影响,您可以使用混合方法并切掉一些最重要的位(机器字长可以)。运行一个生成器,为这部分返回一个合适的数字,为 LSB 部分返回随机位,结果很有可能是可用的。
      【解决方案5】:

      如果您有一个随机数生成器,可以生成 X 位的随机数。并且 [X1, X2, ... Xn ] 的级联位创建您想要的 N 位数字,只要每个 X 是随机的,我不明白为什么您的大数字对于所有意图都不会是随机的和目的。如果标准 C rand() 方法不够安全,我敢肯定还有很多其他库(如本线程中提到的那些)其伪随机数“更随机”。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-09-07
        • 2014-09-03
        • 2010-11-11
        • 2013-08-02
        • 1970-01-01
        • 2018-10-02
        相关资源
        最近更新 更多