簡體   English   中英

自定義隨機數生成器

[英]Custom Random Number Generator

是否有可能獲得一個非常快速但可靠的偽隨機數生成器(相同的輸入=相同的輸出,所以我不能使用時間)? 我希望最終結果類似於float NumGen( int x, int y, int seed ); 以便根據這三個值創建一個介於0和1之間的隨機數。 我找到了幾個隨機數生成器,但是我無法使它們正常工作,並且Unity附帶的隨機數生成器使用起來很慢。 我必須在每1米的地形上對生成器進行9次調用,因此我並不在乎它是否在統計上不是完全隨機的,只是它的運行速度非常快。 有人知道適合我需求的算法嗎? 謝謝 :)

我認為您低估了System.Random類。 這是相當快的。 我相信您的速度降低與每次調用NumGen方法時創建Random類的新實例有關。

在我的快速測試中,我能夠在大約1毫秒內使用System.Random生成100,000個隨機數。

為避免速度變慢,請考慮2D平面中的種子點。 分散種子點,使其覆蓋范圍不超過100,000米。 然后關聯(或計算)每米的最近種子點,並將該點用作System.Random的種子。

是的,您將生成大量您永遠不會使用的隨機數,但是它們實際上是免費的。

偽代碼:

double NumGen(x, y, distance, seed) {
  Random random = new Random(seed);
  double result = 0;
  for (int i=0; i<distance; i++) {
    result = random.NextDouble();
  }
}

您可以修改此簡單輪廓以返回隨機數序列(可能表示一個網格),並將其與緩存機制結合使用。 這樣可以節省內存並改善(減少)CPU消耗。

我想您必須在每次調用NumGen時創建一個Random實例。 要使函數為相同的參數返回相同的數字,可以使用哈希函數。

我測試了幾件事,並且此代碼比重新創建Random實例大約快3倍。

//System.Security.Cryptography
static MD5 hasher = MD5.Create();
static byte[] outbuf;
static byte[] inbuf = new byte[12];
static float floatHash(uint x, uint y, uint z) {
    inbuf[0]= (byte)(x >> 24);
    inbuf[1]=(byte)(x >> 16);
    inbuf[2]=(byte)(x >> 8);
    inbuf[3]=(byte)(x);
    inbuf[4]=(byte)(y >> 24);
    inbuf[5]=(byte)(y >> 16);
    inbuf[6]=(byte)(y >> 8);
    inbuf[7]=(byte)(y);
    inbuf[8]=(byte)(z >> 24);
    inbuf[9]=(byte)(z >> 16);
    inbuf[10]=(byte)(z >> 8);
    inbuf[11]=(byte)(z);
    outbuf = hasher.ComputeHash(inbuf);
    return ((float)BitConverter.ToUInt64(outbuf, 0))/ulong.MaxValue;
}

使用某些RSA方法的另一種方法比新的System.Random(seed)快約5倍:

static uint prime = 4294967291;
static uint ord = 4294967290;
static uint generator = 4294967279;
static uint sy;
static uint xs;
static uint xy;
static float getFloat(uint x, uint y, uint seed) {
    //will return values 1=> x >0; replace 'ord' with 'prime' to get 1> x >0
    //one call to modPow would be enough if all data fits into an ulong
    sy = modPow(generator, (((ulong)seed) << 32) + (ulong)y, prime);
    xs = modPow(generator, (((ulong)x) << 32) + (ulong)seed, prime);
    xy = modPow(generator, (((ulong)sy) << 32) + (ulong)xy, prime);
    return ((float)xy) / ord;
}
static ulong b;
static ulong ret;
static uint modPow(uint bb, ulong e, uint m) {
    b = bb;
    ret = 1;
    while (e > 0) {
        if (e % 2 == 1) {
            ret = (ret * b) % m;
        }
        e = e >> 1;
        b = (b * b) % m;
    }
    return (uint)ret;
}

我進行了一次測試,生成了100000個浮動。 我將索引用作System.Random的種子,並用作floatHash的x參數(y和z為0)。

System.Random:最小值:2.921559E-06最大值:0.9999979重復次數:0

floatHash MD5:最小值:7.011156E-06最大值:0.9999931重復:210(值被返回兩次)

getFloat RSA:最小值:1.547858E-06最大值:0.9999989重復次數:190

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM