随机浮点数

13

我编写了这个函数来获取一个介于0和1之间(包括0和1)的伪随机浮点数:

float randomFloat()
{
      float r = (float)rand()/(float)RAND_MAX;
      return r;
}

然而,它始终返回0.563585。无论我运行控制台应用程序多少次,这个数字都相同。

编辑:

如果需要,这是我的整个应用程序:

#include <stdio.h>
#include <stdlib.h>

float randomFloat()
{
      float r = (float)rand() / (float)RAND_MAX;
      return r;
}

int main(int argc, char *argv[])
{
  float x[] = {
        0.72, 0.91, 0.46, 0.03, 0.12, 0.96, 0.79, 0.46, 0.66, 0.72, 0.35, -0.16,
        -0.04, -0.11, 0.31, 0.00, -0.43, 0.57, -0.47, -0.72, -0.57, -0.25,
        0.47, -0.12, -0.58, -0.48, -0.79, -0.42, -0.76, -0.77
  };

  float y[] = {
        0.82, -0.69, 0.80, 0.93, 0.25, 0.47, -0.75, 0.98, 0.24, -0.15, 0.01,
        0.84, 0.68, 0.10, -0.96, -0.26, -0.65, -0.97, -0.03, -0.64, 0.15, -0.43,
        -0.88, -0.90, 0.62, 0.05, -0.92, -0.09, 0.65, -0.76      
  };

  int outputs[] = {
      -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
      1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
  };

  int patternCount = sizeof(x) / sizeof(int);

  float weights[2];
  weights[0] = randomFloat();
  weights[1] = randomFloat();

  printf("%f\n", weights[1]);

  float learningRate = 0.1;

  system("PAUSE");
  return 0;
}

3
注意,rand()函数不一定是一个非常“好”的随机数生成器。如果您只需要在0到1之间保留两位小数,则可能无关紧要;但如果您需要四个或更多的小数位数,则会产生影响。如果您需要更多的小数位数,请查看drand48()函数族:http://www.opengroup.org/onlinepubs/9699919799/functions/drand48.html - Jonathan Leffler
5个回答

14

你需要调用

srand(time(NULL));

在第一次使用rand之前,需要先使用<time.h>中的time函数。

编辑:正如Jonathan Leffler所指出的那样,这很容易被预测,因此不要尝试将其用于加密。


2
使用time()函数要小心,因为它很容易被预测,从而使您的随机序列也能够被预测。在这种情况下可能无关紧要,但一般情况下要小心。 - Jonathan Leffler

10

这是因为C语言的随机数生成器是伪随机生成器(pseudo-random generator),这是一件非常好的事情,有很多实际应用。(ANSI C标准要求使用该种伪随机生成器)。

基本上每次重新启动控制台应用程序时,它都会使用相同的[默认]种子来进行随机数生成。

通过添加类似以下这行代码:

  srand(time(NULL));

每次调用rand()函数时,你将会得到一个不同的种子,并且产生的数字序列也会相应地有所变化。
注意:只需要在第一次调用rand()之前调用srand()一次即可。

编辑:(测试/调试提示)
[来自Artelius的评论]
为了测试目的,最好使用srand(SOME_CONST),并在运行之间更改常量的值。这样,如果由于一些随机数的组合而出现错误,您将能够重现它。


5
为了进行测试,最好使用srand(SOME_CONST)函数,并在每次运行时更改常量的值。这样,如果由于某些随机数的组合而出现了错误,您就可以重现它。 - Artelius
@artelius,非常好的建议。我已经将其作为响应本身的注释添加了! - mjv
@artelius和mjv:这确实是一个好观点;允许用户在命令行上指定种子而不是使用time()也可以是一个好主意,通常情况下(但并非总是如此),报告所使用的种子(无论来自命令行还是其他来源)有利于处理结果。 - Jonathan Leffler

6
drand48非常适合您的使用,比(float)rand()/RAND_MAX更好,因为 drand48()erand48()函数返回非负的双精度浮点数值,均匀分布在区间[0.0,1.0]中。请注意保留HTML标记。
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main() {
    int i;

    srand48(time(NULL));

    for (i = 0; i < 10; i++)
        printf("%g\n", drand48());

    return 0;
}

2
您需要使用一个随机种子进行初始化。
void srand ( unsigned int seed );

你可以以系统时间为例。

1
你是否调用了超过一次?rand()将始终返回相同的伪随机数。您可能希望使用一些好的种子调用srand(),例如当前时间。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接