我遇到了rgba的浮点随机数生成器:
http://rgba.org/articles/sfrand/sfrand.htm
解释清楚,代码很简单。有一个问题:我无法弄清楚随机位的来源。以下代码段:
static unsigned int mirand = 1;
float sfrand( void )
{
unsigned int a;
mirand *= 16807;
a = (mirand&0x007fffff) | 0x40000000;
return( *((float*)&a) - 3.0f );
}
我确实尝试compile this function并且总是得到-0.995993
的结果,如果mirand
以1
开头,这是有道理的。我错过了什么,或者mirand
只是种子?
答案 0 :(得分:6)
事实是,该代码不会生成随机数...它会生成伪随机数字。假设你从相同的种子开始,外行人想象发生了什么的方式是你正在经历一个巨大的“随机”数字列表。最终,这些数字会重演,但一个好的公式就是让这个重复发生在很大的间隔。
为了澄清,请查看Excel使用的rand公式:http://support.microsoft.com/kb/828795
答案 1 :(得分:1)
每次获得相同数字的原因是因为这实际上是一个伪随机数生成器,就像常规数字生成器一样。它没有种子,所以你总是在第n次调用时得到相同的值。如果您对sfrand进行多次后续调用,您将看到结果,它们在-1和1之间是统一的:
-0.995993
0.347347
-0.130602
0.970146
-0.749159
0.883045
就像你在没有播种的情况下调用正常的rand()函数一样,你会看到相同的序列。正如所讨论的那样,选择数字16807是有充分理由的,所以你可以通过随机调用函数来播种这个数字:
static unsigned int mirand = 1;
float sfrand(double seed)
{
unsigned int a;
mirand *= seed;
a = (mirand&0x007fffff) | 0x40000000;
return( *((float*)&a) - 3.0f );
}
int main()
{
srand(time(NULL));
int count = rand() % 1000 + 1
for(int i = 0; i < count; ++i)
sfrand();
}
这将丢弃第一个计数值,同时仍然为您提供随机种子,并且所有后续调用仍将获得该函数预期的性能提升。后续调用现在返回唯一值:
codys-macbook-pro:~ cody$ ./a.out
0.166836
codys-macbook-pro:~ cody$ ./a.out
0.256372
codys-macbook-pro:~ cody$ ./a.out
-0.194259
codys-macbook-pro:~ cody$ ./a.out
-0.556834