此代码中的哪个位置生成一个随机数?

时间:2011-11-13 04:58:26

标签: c random floating-point

我遇到了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的结果,如果mirand1开头,这是有道理的。我错过了什么,或者mirand只是种子?

2 个答案:

答案 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