简体   繁体   English

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

[英]Where in this code generates a random number?

I came across rgba 's floating point random number generator: 我遇到了rgba的浮点随机数生成器:

http://rgba.org/articles/sfrand/sfrand.htm http://rgba.org/articles/sfrand/sfrand.htm

The explanation is clear and the code is simple. 解释清楚,代码很简单。 There is one issue: I cannot figure out where the random bits come from. 有一个问题:我无法弄清楚随机位的来源。 Code snippet below: 以下代码段:

static unsigned int mirand = 1;

float sfrand( void )
{
    unsigned int a;
    mirand *= 16807;
    a = (mirand&0x007fffff) | 0x40000000;
    return( *((float*)&a) - 3.0f );
}

I did try to compile this function and always get a result of -0.995993 , which makes sense if mirand starts out as 1 . 我确实尝试编译这个函数并且总是得到-0.995993的结果,如果mirand1开始是有意义的。 What am I missing, or is mirand simply the seed? 我在想什么,或者是mirand简单的种子?

Truth is, that code does NOT generate random numbers... it generates pseudo-random numbers. 事实是,该代码不会生成随机数...它会生成伪随机数。 Assuming you start with the same seed, a layman's way to imagine what's happening is that you are just going through a HUGE list of "random" numbers. 假设你从相同的种子开始,外行人想象发生了什么的方式是你正在经历一个巨大的“随机”数字列表。 Eventually, the numbers will repeat themselves, but a good formula is one that makes this repetition happen at a large interval. 最终,数字将重复,但一个好的公式是使这种重复发生在一个很大的间隔。

To clarify, take a look at the rand formula that Excel uses: http://support.microsoft.com/kb/828795 为了澄清,请查看Excel使用的rand公式: http//support.microsoft.com/kb/828795

The reason you're getting the same number every time is because this is in fact a pseudo random number generator just like regular ones. 你每次获得相同数字的原因是因为这实际上是一个伪随机数生成器,就像常规数字生成器一样。 It has no seed so you will always get the same value on the nth call. 它没有种子,所以你总是在第n次调用时得到相同的值。 If you make several subsequent calls to sfrand you'll see the results, which are uniform between -1 and 1: 如果您对sfrand进行多次后续调用,您将看到结果,这些结果在-1和1之间是均匀的:

-0.995993
0.347347
-0.130602
0.970146
-0.749159
0.883045

Just like if you were to call the normal rand() function without seeding it you'd see the same sequence. 就像你在没有播种的情况下调用普通的rand()函数一样,你会看到相同的序列。 As discussed the number 16807 was chosen for good reason, so you can seed this number by calling the function a random number of times: 正如所讨论的那样,选择数字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();
}

This will just discard the first count values while still giving you a random seed, and all subsequent calls will still gain the performance boost intended by the function. 这将丢弃第一个计数值,同时仍然为您提供随机种子,并且所有后续调用仍将获得该函数预期的性能提升。 Subsequent calls now return unique values: 后续调用现在返回唯一值:

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

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

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