Random.Next() - 找到Nth .Next()

时间:2011-03-22 00:43:24

标签: c# random perlin-noise

给出一直播种的随机:

Random r = new Random(0);

调用r.Next()始终生成相同的系列;那么有没有办法快速发现该系列中的 N -th值,而无需调用r.Next() N 次?

我的场景是通过r.Next()创建的大量值。应用程序偶尔会在任意索引处从数组中读取值。我想通过消除数组来优化内存使用,而是根据需要生成值。但强迫r.Next() 500万次模拟数组的第500万个索引比存储数组更昂贵。是否有可能缩短你的方式到Nth .Next()值,没有/少循环?

4 个答案:

答案 0 :(得分:6)

我不知道BCL中使用的PRNG的细节,但我的猜测是你会发现很难/不可能为 N 找到一个漂亮的,封闭式的解决方案 - 该系列的价值。

这个解决方法怎么样:

种子设为随机数生成器所需的索引,然后选择第一个生成的数字。这同样是“确定性的”,并且在O(1)空间中为您提供了广泛的范围。

static int GetRandomNumber(int index)
{
    return new Random(index).Next();
} 

答案 1 :(得分:2)

理论上如果您知道确切的算法和初始状态,您就可以复制该系列,但最终结果与调用r.next()完全相同。

根据您需要随机数的“好”程度,您可以考虑根据Linear congruential generator创建自己的PRNG,这相对容易/快速生成数字。如果您可以使用“坏”PRNG,可能还有其他算法可能更适合您的目的。这是否比从r.next()存储大量数字更快/更好是另一个问题。

答案 2 :(得分:1)

不,我不相信有。对于某些RNG算法(例如线性同余生成器),原则上可以在不迭代n步的情况下获得第n个值,但Random类不提供这样做的方法。

我不确定它使用的算法原则上是否可行 - 它是Knuth的减法RNG的变体(文档中未公开的细节),看起来原始的Knuth RNG应该等同于某种类型的允许访问第n个值的多项式算术,但(1)我实际上没有检查过这个,(2)微软所做的任何调整都可能会破坏它。

如果你有一个足够好的“加扰”函数f那么你可以使用f(0),f(1),f(2),...作为你的随机数序列,而不是f(0), f(f(0)),f(f(f(0)))等(后者大致大多数RNG所做的事情)然后当然在任何时候启动序列都是微不足道的请你点。但是你需要选择一个好的f,它可能比标准RNG慢。

答案 3 :(得分:0)

您可以构建自己的“索引”按需词典& '随机价值'。这假设您每次程序运行时始终以相同的顺序“请求”索引,或者您不关心每次程序运行时结果是否相同。

Random rnd = new Random(0);
Dictionary<int,int> randomNumbers = new Dictionary<int,int>();
int getRandomNumber(int index)
{
    if (!randomNumbers.ContainsKey(index))
        randomNumbers[index] = rnd.Next();
    return randomNumbers[index];
}