简体   繁体   English

与彩票调度程序的LCG相比,更好的(伪)随机数发生器是什么?

[英]What are the better (pseudo) random number generator than the LCG for lottery scheduler?

I want to design a lottery scheduler and I need to have a very good (pseudo) random number generator similar to LCG but I was wondering if there are other better choice out there or not? 我想设计一个彩票调度器,我需要一个非常好的(伪)随机数发生器,类似于LCG,但我想知道是否还有其他更好的选择? I am specifically looking for random generators written in C. 我特意寻找用C语言编写的随机生成器。

LCG code: LCG代码:

unsigned long lcg_rand(unsigned long a)
{
  return (a * 279470273UL) % 4294967291UL;
}

Also I would like to know if srand() can be used for this purpose or is not highly accurate? 另外我想知道srand()可以用于此目的或不是非常准确?

If you need simple but decent quality, I would use the upper 32 (or fewer) bits of a 64-bit LCG, possibly with a tempering function applied to the output. 如果你需要简单但体面的质量,我会使用64位LCG的高32位(或更少),可能还有一个应用于输出的回火功能。 When doing this, I've copied the tempering function used in Mersenne Twister . 这样做时,我复制了Mersenne Twister中使用的回火功能。 I would not recommend actually using Mersenne Twister, as it has a lot more complexity and internal state than other PRNGs without significantly better qualities. 我不建议实际使用Mersenne Twister,因为它比其他PRNG具有更多的复杂性和内部状态而没有明显更好的品质。

Here is some sample code: 以下是一些示例代码:

static uint32_t temper(uint32_t x)
{
    x ^= x>>11;
    x ^= x<<7 & 0x9D2C5680;
    x ^= x<<15 & 0xEFC60000;
    x ^= x>>18;
    return x;
}
uint32_t lcg64_temper(uint64_t *seed)
{
    *seed = 6364136223846793005ULL * *seed + 1;
    return temper(*seed >> 32);
}

Mersenne Twister would be one option. Mersenne Twister是一个选择。 Another option is Subtract with carry 另一种选择是减去携带

most implementations of the C rand() function use variations of LGC . C rand()函数的大多数实现都使用LGC的变体。 rand() , like any computerized random generator is not truly random, it is only pseudo random. rand() ,就像任何计算机化的随机生成器不是真正随机的,它只是伪随机的。 Using srand() can improve randomness, but not make it perfect. 使用srand()可以改善随机性,但不能使其完美。 It depends on how varied and random the seed used in srand() is. 它取决于srand()使用的种子的变化和随机性。 For example if you called rand() n times using the same identical seed in srand() , the results would be the same. 例如,如果你在srand()使用相同的相同种子n次调用rand() n次,结果将是相同的。 But if you called srand(clock()) each time (and the elapsed time between calls was greater than the period of ticks in clock() ), then you would have an improved random generator. 但是如果你每次都调用srand(clock()) (并且调用之间经过的时间大于clock()的ticks周期),那么你将拥有一个改进的随机生成器。

Here is a simple code example, where both clock() and a support function, NotRecentlyUsed() (for small samples of min and max ) are used: 这是一个简单的代码示例,其中使用了clock()和支持函数NotRecentlyUsed() (对于minmax的小样本):

#include <ansi_c.h>

#define _UNIQUE_

int randomGenerator(int min, int max);
int NotUsedRecently (int number);

int main(void)
{
    int i=0;
    for(i=0;i<1000;i++)
    {
        printf("%d,\t", randomGenerator(0, 20));
            if(i%20 == 0) printf("\n");
    }
    getchar();
    return 0;   
}

//////////////////////////////////////////////////////
//generates pseudo random numbers between min and max
//If it is desired to use this without a guarantee of uniqueness
//for a specified span of values, un-define _UNIQUE_
//
int randomGenerator(int min, int max)
{
    int random, trying;

    trying = 1;         
    while(trying)
    {
        srand(clock());
        random = (rand()/32767.0)*(max+1);
        ((random >= min)
#ifdef _UNIQUE_
            && NotUsedRecently(random) 
#endif
            ) ? (trying = 0) : (trying = 1);
    }

    return random;
}

//This function is used to guarantee that a span of n generated values
//will not be the same. To adjust the span, change the index in 
//static int recent[n];  Note: it is required that n < (max-min)
//otherwise an infinite loop will occur
int NotUsedRecently (int number)
{
    static int recent[20];//Use No greater value for index than max - min
    int i,j;
    int notUsed = 1;

    for(i=0;i<(sizeof(recent)/sizeof(recent[0]));i++)  (number != recent[i]) ? (notUsed==notUsed) : (notUsed=0, i=(sizeof(recent)/sizeof(recent[0])));
    if(notUsed) 
    {
        for(j=(sizeof(recent)/sizeof(recent[0]));j>1;j--)
        {
            recent[j-1] = recent[j-2];
        }
        recent[j-1] = number;
    }
    return notUsed;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM