用于程序内容的快速伪随机数生成器

问题描述 投票:0回答:7

我正在寻找一个伪随机数生成器,当在生成每个数字之前给它一个种子时,它会专门快速工作。到目前为止,我见过的大多数生成器都假设您设置一次种子,然后生成一长串数字。到目前为止,唯一看起来与我所见过的有点相似的是柏林噪声,但它生成的数据过于“平滑”——对于相似的输入,它往往会产生相似的结果。

生成器的声明应该类似于:

int RandomNumber1(int seed);

或者:

int RandomNumber3(int seedX, int seedY, int seedZ);

我认为拥有好的 RandomNumber1 应该就足够了,因为可以通过散列其输入并将结果传递到 RandomNumber1 来实现 RandomNumber3,但我编写了第二个原型,以防某些实现可以使用独立输入。

该生成器的预期用途是将其用于程序内容生成器,例如通过将树木放置在网格中并确定每个位置的随机树种和随机空间偏移来生成森林。

生成器需要非常高效(低于 500 个 CPU 周期),因为程序内容是在渲染过程中实时大量创建的。

c++ x86 random
7个回答
21
投票

似乎您要求的是哈希函数而不是 PRNG。谷歌搜索“快速哈希函数”产生了一些看起来有希望的结果。

例如

uint32_t hash( uint32_t a)
    a = (a ^ 61) ^ (a >> 16);
    a = a + (a << 3);
    a = a ^ (a >> 4);
    a = a * 0x27d4eb2d;
    a = a ^ (a >> 15);
    return a;
}

编辑:是的,某些哈希函数看起来肯定比其他函数更合适。

为了您的目的,观察该函数并检查输入中的一位变化是否会传播到许多输出位就足够了。


9
投票

是的,您正在寻找快速整数哈希算法而不是 PRNG。

页面有一些算法,我相信您现在知道了正确的搜索词,会发现更多。

编辑:原始页面已被删除,实时版本可以在在GitHub上找到


4
投票

这是 George Marsaglia 开发的一个小型随机数生成器。他是该领域的专家,因此您可以确信生成器具有良好的统计特性。

v = 36969*(v & 65535) + (v >> 16);
u = 18000*(u & 65535) + (u >> 16);
return (v << 16) + (u & 65535);

这里 u 和 v 是无符号整数。将它们初始化为任何非零值。每次生成随机数时,将 u 和 v 存储在某处。您可以将其包装在一个函数中以匹配上面的签名(除非整数是无符号的。)


2
投票

参见

std::tr1::ranlux3
,或其他随机数生成器,它们是 TR1 添加到标准 C++ 库的一部分。我最初建议使用 mt19937,但后来看到你的说明,它需要非常快。 TR1 应该可以在 Microsoft VC++ 和 GCC 上使用,也可以在支持更多编译器的 boost 库中找到。

改编自 boost 文档的示例:

#include <random>
#include <iostream>
#include <iterator>
#include <functional>
#include <algorithm>
#include <ctime>
using namespace std;
using namespace std::tr1;
int main(){
    random_device trueRand;
    ranlux3 rng(trueRand);  // produces randomness out of thin air
                            // see pseudo-random number generators
    uniform_int<> six(1,6); // distribution that maps to 1..6
                            // see random number distributions
    variate_generator<ranlux3&, uniform_int<> >
           die(rng, six);   // glues randomness with mapping

    // simulate rolling a die
    generate_n( ostream_iterator<int>(cout, " "), 10, ref(die));
}

示例输出:

2 4 4 2 4 5 4 3 6 2

任何 TR1 随机数生成器都可以为任何 other 随机数生成器播种。如果您需要更高质量的结果,请考虑将 mt19937 的输出(速度较慢,但质量更高)输入到 minstd_rand 或 randlux3,它们是更快的生成器。


0
投票

如果内存并不是真正的问题并且速度至关重要,那么您可以预先构建大量随机数并在运行时对其进行迭代。例如,有一个单独的程序生成 100,000 个随机数并将其保存为自己的文件,如

无符号 int randarray []={1,2,3,....}

然后将该文件包含到您的编译中,在运行时,您的随机数函数只需要从该数组中提取数字,并在到达末尾时循环回到开头。


0
投票

我在我的 Java 随机数库中使用了以下代码 - 这对我来说效果很好。我还用它来生成程序内容。

/**
 * State for random number generation
 */
private static volatile long state=xorShift64(System.nanoTime()|0xCAFEBABE);

/**
 * Gets a long random value
 * @return Random long value based on static state
 */
public static long nextLong() {
    long a=state;
    state = xorShift64(a);
    return a;
}

/**
 * XORShift algorithm - credit to George Marsaglia!
 * @param a initial state
 * @return new state
 */
public static final long xorShift64(long a) {
    a ^= (a << 21);
    a ^= (a >>> 35);
    a ^= (a << 4);
    return a;
}

0
投票
/* A C-program for TT800 : July 8th 1996 Version 
   by M. Matsumoto, email: m-mat @ math.sci.hiroshima-u.ac.jp

   Refactored and coded much simpler by robert bristow-johnson April 17, 2024

   random_uint32() generates one 32-bit pseudorandom number 
   which is uniformly distributed on the [0, 0xffffffff] interval for
   each call.  One may choose any initial 25 seeds except all zeros.
 
   Copyright (C) 1996, Makoto Matsumoto
   All rights reserved.

   Redistribution and use in source and binary forms, with or without
   modification, are permitted provided that the following conditions
   are met:

     1. Redistributions of source code must retain the above copyright
        notice, this list of conditions and the following disclaimer.

     2. Redistributions in binary form must reproduce the above copyright
        notice, this list of conditions and the following disclaimer in the
        documentation and/or other materials provided with the distribution.

     3. The names of its contributors may not be used to endorse or promote 
        products derived from this software without specific prior written 
        permission.

   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
   PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER 
   OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

   See: ACM Transactions on Modelling and Computer Simulation,
   Vol. 4, No. 3, 1994, pages 254-266.
*/


#include <stdint.h>

#define N 25
#define M 18

uint32_t random_uint32(void)
{
    static int k = 0;

    static uint32_t x[N] = {
    0x95f24dab, 0x0b685215, 0xe76ccae7, 0xaf3ec239, 0x715fad23,
    0x24a590ad, 0x69e4b5ef, 0xbf456141, 0x96bc1b7b, 0xa7bdf825,
    0xc1de75b7, 0x8858a9c9, 0x2da87693, 0xb657f9dd, 0xffdc8a9f,
    0x8121da71, 0x8b823ecb, 0x885d05f5, 0x4e20cd47, 0x5a9ad5d9,
    0x512c0c03, 0xea857ccd, 0x4cc1d30f, 0x8891a8a1, 0xa6b7aadb
    };

    uint32_t y = x[k];            // seed from N iterations earlier

    uint32_t z =  (y >> 1);
    if (y & 0x00000001) z ^= 0x8ebfd028;

    int n = k - M;                // point to seed from M iterations earlier
    if (n < 0) n += N;            // modulo N addressing

    x[k++] = x[n] ^ z;            // update seed
 
    if (k == N) k = 0;            // modulo N addressing

    y ^= (y << 7) & 0x2b5b2500;
    y ^= (y << 15) & 0xdb8b0000;
    y ^= (y >> 16);
    return y;
}
© www.soinside.com 2019 - 2024. All rights reserved.