问题
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? I am specifically looking for random generators written in C.
LCG code:
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?
回答1:
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. When doing this, I've copied the tempering function used in 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.
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);
}
回答2:
Mersenne Twister would be one option. Another option is Subtract with carry
回答3:
most implementations of the C rand()
function use variations of LGC. rand()
, like any computerized random generator is not truly random, it is only pseudo random. Using srand()
can improve randomness, but not make it perfect. It depends on how varied and random the seed used in srand()
is. For example if you called rand()
n times using the same identical seed in srand()
, the results would be the same. 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.
Here is a simple code example, where both clock()
and a support function, NotRecentlyUsed() (for small samples of min and max) are used:
#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;
}
来源:https://stackoverflow.com/questions/19083566/what-are-the-better-pseudo-random-number-generator-than-the-lcg-for-lottery-sc