【问题标题】:Pseudorandom Sequence Generator not just a number generator伪随机序列发生器不仅仅是一个数字发生器
【发布时间】:2009-11-07 04:35:13
【问题描述】:

我需要一种算法,几乎可以将 unix 时间戳转换为适当的随机数,这样如果我“回放”时间戳,我就会得到相同的随机数。

这就是我所说的适当的意思:

  1. 大多数人不会在随机数中检测到循环或模式。
  2. 它不需要是加密安全的。
  3. 必须能够生成所有数字。 (我发现 LFSR 不这样做)
  4. 数字是 32 位整数

而且我希望它相当快。

到目前为止,我的想法是一遍又一遍地播种 PRNG,但我不确定这是否是处理此问题的最佳方法。

任何想法和想法将不胜感激。

谢谢。

【问题讨论】:

  • 如果更改时间戳的顺序,是否希望以不同的顺序获得相同的随机数?例如。从 [(1, 5), (2, 3), (3,9)] 开始,其中一对中的第一个数字是时间戳,你想要 [(2,3), (3,9), (1,5)] 还是 [(2,7), (3,4), (1,6)]?
  • XKCD 来救援! - xkcd.com/221
  • 好点outis,这可以区分散列和prng。
  • @outis,时间戳永远不会乱序播放,但无论如何我都会研究散列,因为它似乎是一个快速的解决方案。

标签: integer random sequence prng


【解决方案1】:

如果它不需要在统计上是随机的,也许可以将时间戳提供给 MD5 并截断散列。主要问题是我不知道这是否是主观的。其他散列算法可能效果更好。

【讨论】:

  • 如果随机数是供人类使用的,则不太可能快速区分散列冲突。 MD4、MD5 会很快。
  • 我将测试散列并查看分布的外观。我想要一些分布接近随机的东西,但如果你发现我的想法,它不必那么接近。
  • 我继续并将其标记为已接受的答案,因为它是我使用的,尽管这里的其他解决方案可能同样有用。
【解决方案2】:

我建议最简单的做法是将您的时间花在jrand48 上。类似的东西

#include <stdlib.h>
int mix(int t) {
    unsigned short x[3] = {t, t<<16, t};
    return jrand48(x);
}

它是可逆的 (216·x+n≡0x5deece66d·(232+1)·t+0xb mod 248 ⇒ t≡0xdfe05bcb1365·(216·x+n-0xb) mod 248 其中 n∈[0,216)) 但因为它是48位中的高32位,实际上并不容易。 (您也可以多次将jrand48 应用到x;只要不应用248-1 次,相同类型的属性将成立。)

【讨论】:

  • 我不了解可逆性以了解我是否需要它。这实质上是在获取生成的数字并取回种子(时间戳)吗?
  • 是的。将x 视为48 位数字,我们设置x=(2^32+1)*t,然后jrand48 将其更改为0x5deece66d*x+0xb 并返回高32 位。只需要一点模运算就可以计算出逆运算,即从jrand48 的输出返回到原始t。这通常不是一般情况(32 位输出不足以确定 48 位状态),但由于我们只有 32 位输入,所以它就在这里。
  • 你的意思是't>>16'而不是't
【解决方案3】:

我建议查看符合 POSIX 的 drand48() 系列函数。它们给出了不错的(但肯定不是加密的)随机数,srand48() 采用 32 位种子值。它们是确定性的,因此重用给定的种子将再次重新生成相同的数字序列。

【讨论】:

  • 我之前没有看到你的回答;我的差不多,但使用(erand48/nrand48/jrand48) 比srand48+(drand48/lrand48/mrand48) 更直接。
  • @ephemient:全在家里 :-)
【解决方案4】:

(timestamp ^ 0x12345678) + 12345678这够微妙吗?

如果您不关心它的可逆性,您可以对每个时间戳进行 crc32。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-11-18
    • 2019-12-15
    相关资源
    最近更新 更多