glibc rand函数实现 [英] glibc rand function implementation

查看:253
本文介绍了glibc rand函数实现的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在阅读 c标准库rand()函数实现带有glibc源代码. stdlib/random_r.c,第359行

I'm reading c standard library rand() function implementation with glibc source code. stdlib/random_r.c, line 359

int
__random_r (buf, result)
            struct random_data *buf;
            int32_t *result;
{
  int32_t *state;

  if (buf == NULL || result == NULL)
    goto fail;

  state = buf->state;

  if (buf->rand_type == TYPE_0)
    {
      int32_t val = state[0];
      val = ((state[0] * 1103515245) + 12345) & 0x7fffffff;
      state[0] = val;
      *result = val;
    }
  else
    {
      int32_t *fptr = buf->fptr;
      int32_t *rptr = buf->rptr;
      int32_t *end_ptr = buf->end_ptr;
      int32_t val;

      val = *fptr += *rptr;
      /* Chucking least random bit.  */
      *result = (val >> 1) & 0x7fffffff;
      ++fptr;
      if (fptr >= end_ptr)
        {
          fptr = state;
          ++rptr;
        }
      else
        {
          ++rptr;
          if (rptr >= end_ptr)
            rptr = state;
        }
      buf->fptr = fptr;
      buf->rptr = rptr;
    }
  return 0;

 fail:
  __set_errno (EINVAL);
  return -1;
}

我不明白(buf->rand_type != TYPE_0)时random_r如何生成随机数,请问有人解释吗?谢谢.

I don't understand how random_r generate random number when (buf->rand_type != TYPE_0), anyone please explain? Thanks.

推荐答案

glibc rand()具有两种不同的生成器实现:

glibc rand() has two different generator implementations:

  1. 一个简单的线性同余生成器(LCG),由以下等式定义:

  1. A simple linear congruential generator (LCG), defined by the following equation:

val = ((state * 1103515245) + 12345) & 0x7fffffff

(& 0x7fffffff丢弃最小随机最高有效位)

(& 0x7fffffff throws away the least random most significant bit)

这是一个非常简单的单状态LCG.它有一些缺点.最重要的是,因为它是一个状态生成器,所以不会在每个单独的rand()调用上生成完全伪随机数.真正的作用是它以伪随机顺序遍历整个范围(2 ^ 31).这有一个有意义的含义:当您获取某个号码时,这意味着您将在当前期间再次获取该号码.您将在下一个2 ^ 31 rand()调用中再次准确地获得该号码,而不会再迟了.

This is a very simple, single state LCG. It has some drawbacks. The most important one is that, because it is a single state generator, it does not generate a fully pseudorandom number on each separate rand() call. What it really does is that it traverses the whole range (2^31) in a pseudorandom order. This has a meaningful implication: when you obtain some number it means that you will not obtain that number again in the present period. You will obtain that number again exactly in the next 2^31 rand() call, no sooner, no later.

此生成器在glibc源中称为TYPE_0.

稍微高级一点的加性反馈生成器.该生成器具有许多状态,这意味着它不具有上述的遍历属性".您可以在同一时期内两次(或多次)获得相同的数字.

A slightly more advanced, additive feedback generator. That generator has many states, which means that it does not have the "traverse property" described above. You can get the same number twice (or more times) during the same period.

您可以在此处找到一个很好的描述.

You can find an excellent description of that algorithm here.

此生成器在glibc源中称为TYPE_1TYPE_2TYPE_3TYPE_4.

This generator is called the TYPE_1, TYPE_2, TYPE_3 or TYPE_4 in the glibc source.

回到您的问题,即它如何生成值:

Coming back to your question, that is how it generates values:

seeding_stage() // (code omitted here, see the description from above link)

for (i=344; i<MAX; i++)
{
    r[i] = r[i-31] + r[i-3];
    val = ((unsigned int) r[i]) >> 1;
}

您问题中的else之后的代码只是上面的代码,但是以不同的方式编写(使用指向包含先前值的数组的指针).

The code after the else in your question is simply the above code, but written in a different way (using pointers to the array containing previous values).

使用哪种生成器取决于使用 initstate() 功能.仅当状态大小为8个字节时才使用第一个(LCG)生成器.当它更大时,将使用第二个发电机.使用srand()设置种子时,默认情况下状态的大小为128字节,因此使用第二个生成器.一切都写在您在问题中引用的glibc源文件中的注释中.

Which generator is used depends on the size of the initial state set with the initstate() function. The first (LCG) generator is used only when state size is 8 bytes. When it is bigger, the second generator is used. When you set your seed using srand() the size of the state is 128 bytes by default, so the second generator is used. Everything is written in comments in the glibc source file referenced by you in your question.

这篇关于glibc rand函数实现的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆