无法理解C中的PRNG代码

时间:2011-05-18 17:00:34

标签: c random numbers generator prng

#include <stdio.h>


double seed=0.579832467;

main(ac, av)
int ac;
char *av[];
  {
   /* declare variables */
   float *buf, fac;
   int sf, ne, i;

   /* prototypes? ( shouldn't they be outside the main ) */
   double rnd(), sd;

   /* gets the number of elements from command line */
   ne = atoi(av[1]);

   /* assigns the size of float ( in bytes ) to integer value */
   sf = sizeof(float);

   /* allocates appropriate memory for random number generation */
   buf = (float *)malloc(ne*sf);

   /* type cast, why?? */
   sd = (double)(ne);

   /* no idea what initrnd does */
   initrnd(sd/(sd+187.9753));

   /* checks if memory allocation is successful */
   if (buf == NULL)
     {
      fprintf(stderr, "rndneg: can't allocate %d bytes for buffer\n", ne*sf);
      exit(-1);
     }

   /* fills buffer with random number */
   for (i=0; i<ne; i++)
    {
     buf[i] = (float)(rnd());
    }

   /* writes the buffer, how does it know the file name? */ 
   write(1, buf, ne*sf);
}

/* random number generating function */
double rnd()
{
seed *= 997.0;
seed -= (double)((int)(seed));
return(seed);
}


initrnd(sd)

/* again no idea, why isn't this function void */
double sd;
{
seed = sd;
return(0);
}

这是PRNG的一些代码。我对C不太熟悉,而且这段代码中的一些内容对我来说完全没有意义。我试图评论代码来跟踪发生了什么。如果我不明白的一些事情可以被清除,我将不胜感激。特别是具有相同名称的变量和函数的声明,以及initrnd子例程,似乎没有在程序或我在互联网上找到的任何库中定义。

非常感谢。

3 个答案:

答案 0 :(得分:2)

这看起来很古老。

您的问题的几个答案:

  1. 不,原型不需要是外部功能。这可能是最常见的,但不是必需的。
  2. initrnd()只需将全局seed变量设置为特定值,然后在PRNG中使用。
  3. 数据写入stdout;假设使用文件描述符1。这种神奇常数的使用不是很漂亮,应该写成stdout(来自<stdio.h>)。

答案 1 :(得分:1)

   /* type cast, why?? */
   sd = (double)(ne);

因为ne是一个整数而sd是double,所以需要强制转换

   /* no idea what initrnd does */
   initrnd(sd/(sd+187.9753));

它是最后一个函数,它使用参数

设置全局变量种子
   /* writes the buffer, how does it know the file name? */ 
   write(1, buf, ne*sf);

文件描述符是1,代表标准输出,所以这就像调用printf()

initrnd(sd)

/* again no idea, why isn't this function void */

这个函数是int,但它应该是void(无论如何都没有任何区别),也许原来的程序员很懒:P

答案 2 :(得分:0)

代码是预标准的C,所以它不使用原型(但确实声明了函数,但显然不是绝对必要的)。函数定义使用预标准K&amp; R样式来声明函数的参数。对于非原型类型的函数,程序员有责任确保使用正确的参数集调用函数,并且如果函数没有返回任何内容,则函数的“值”不会执行任何操作。

如果函数返回了int以外的函数,则必须声明该函数(不一定是原型),因此编译器会知道函数返回的数据类型。如果没有声明,编译器将假定返回int(但如果函数没有返回任何内容,只要您不尝试对函数'result'执行任何操作,那就没问题。)

以下是对您的问题的一些直接评论:

   /* prototypes? ( shouldn't they be outside the main ) */
   //   this declares that function `rnd()` returns a double.  Technically, it's 
   //   not a prototype. Without the declaration the compiler would assume that it 
   //   returns an `int` so trying to use it wouldn't work.  It could be declared 
   //   outside `main()`, but it's OK to have it declared within the scope of 
   //   `main()`, just like it would be for a prototype.  That just means that 
   //    outside of `main()` the declaration is no longer in effect, so any calls
   //    to `rnd()` would assume that `int` is returned (incorrectly).
   double rnd(), sd;


   /* type cast, why?? */
   //   the cast is unnecessary and redundant, but OK
   sd = (double)(ne);

   /* no idea what initrnd does */
   //   apparently `initrnd()` initializes the rng seed (see below). There's
   //   no declaration in sight, so the compiler will default the return type 
   //   to `int` (unless it's in `stdio.h`).
   initrnd(sd/(sd+187.9753));

   /* writes the buffer, how does it know the file name? */ 
   //   `1` is the file descriptor for `stdout`.  Today this would probably
   //   be specified using `STDOUT_FILENO`, but even today `STDOUT_FILENO` is 
   //   required to be 1 (by POSIX).
   write(1, buf, ne*sf);
}

initrnd(sd)

/* again no idea, why isn't this function void */
//  `void` didn't exist pre-ANSI standard.
//  so this function 'returns' `int` by default.
double sd;
{
seed = sd;
return(0);
}