【问题标题】:How does one write a repeatable pseudo random number generator? [closed]如何编写可重复的伪随机数生成器? [关闭]
【发布时间】:2014-03-21 12:23:02
【问题描述】:

例如:

如果rprng(seed,index) 是我的函数,那么对于任何一对(seed,index),对于给定的(seed,index),我应该总是得到相同的值。

例如:

rprng(4,2) = 17
rprng(4,5) = 21
rprng(4,2) = 17 

【问题讨论】:

  • 但它必须是伪随机的!
  • 伪随机!=随机。伪随机仍然只是数学。
  • 好吧,从头开始。你只是看起来你没有做任何研究。看看现有的不错的 PRNG,例如带进位的乘法、线性同余生成器,或者如果你能忍受的话,那就是 Mersenne twister。你怎么了?您不应该自己创建一个好的、原始的 PRNG,事实上您可能不应该尝试。此外,您的符号 不寻常。 PRNG 通常被认为是流而不是随机访问,即prng(state) 返回下一个数字并改变状态,像prng(seed, i)(通常称为skip)这样的函数要么不存在,要么是次要的。
  • 使用散列函数。我会使用 SipHash(可能轮数更少),以种子为键,索引为消息。
  • @delnan,PRNG 通常被作为流来讨论是非常正确的,而 John 所要求的那种特性是不存在的或次要的。这就是为什么约翰可能进行了研究但没有找到他需要的东西。在某些重要领域(如程序纹理),对 PR 编号的“随机访问”(混淆使用术语)很重要:或者换句话说,PRNG 需要是无状态的,以便我们可以重新计算 random(a1, a2, ... a) 在许多不同的线程上,在许多显示帧上,并且始终获得一致的结果。

标签: c++ objective-c c random


【解决方案1】:

一个简单的想法是使用一个非常彻底的 PRNG,以使seedseed+1seed+2... 生成的值是可接受的随机值。例如:

#include <random>

unsigned prng(unsigned seed, unsigned index)
{
  thread_local std::mt19937 engine;  // or a different engine
  engine.seed(seed + index);

  return engine();
}

也可以查看这个帖子:https://mathoverflow.net/questions/104915/pseudo-random-algorithm-allowing-o1-computation-of-nth-element

【讨论】:

  • 实际上,从顺序播种的 PRNG 中获取第 0 个随机数通常是不可接受的随机数。请参阅“我不能只使用具有不同种子值的随机数生成器吗?”下的blogs.unity3d.com/2015/01/07/…。正是在哪里解决了这种“常见的误解”,并证明了糟糕的结果。当大多数 PRNG 的设计目的不是以这种方式使用时,您如何找到“如此彻底”的 PRNG?但是,您在 mathoverflow.net 上链接到的问题确实有很好的答案:使用(好的)散列或 LFSR。
  • @LarsH 非常有趣的评论。也许 Mersenne Twister 的单值构造函数执行简单(某种)热身(例如stackoverflow.com/a/15509942/3235496 和 cmets)这一事实可以缓解这样的问题(?)
  • 也许吧。这将是值得测试的。一个测试是将以此方式生成的前 65536 个值绘制为 256x256 网格上的灰度值。另一种是在以这种方式生成的前65536个坐标对处画一个白点。 (也来自blogs.unity3d.com/2015/01/07/…
【解决方案2】:

使用 srand(seed) 并且随后对 myval=rand() 的所有使用都是伪随机的。我经常使用这种方法,因为它是从任何给定种子中获取相同值的最简单方法。

【讨论】:

    【解决方案3】:
    int rprng(int seed, int index){
        srand(seed);
        while(index-- >0)
            rand();
        return rand();
    }
    

    【讨论】:

    • 虽然这是正确的,但时间复杂度是 O(index),即线性。当有好的恒定时间算法可供选择时,为什么要使用效率低下的算法?见mathoverflow.net/questions/104915/…
    猜你喜欢
    • 2017-12-25
    • 2016-12-04
    • 2016-12-14
    • 2014-03-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-09
    • 2020-07-24
    相关资源
    最近更新 更多