生成-1和1之间的随机双精度

我已经做了一段时间并且遇到了很多麻烦。 我想生成一个从-1到1的随机值进行计算。 我不能使用%运算符,因为它仅适用于整数。 我也尝试过使用fmod()但我也遇到了困难。

我试图使用的是……

 double random_value; random_value = fmod((double) rand(),2) + (-1); 

看起来它似乎不正确。 我也尝试用时间播种srand,但我认为我在那里做错了,因为它一直在抛出这个错误:

 "error: expected declaration specifiers or '...' before time" 

码:

 srand((unsigned) time(&t)); 

任何有关这些问题的帮助都会受到赞赏。

这将为随机数生成器播种,并在-1.0到1.0的范围内给出一个double

 #include  #include  #include  int main() { double random_value; srand ( time ( NULL)); random_value = (double)rand()/RAND_MAX*2.0-1.0;//float in range -1 to 1 printf ( "%f\n", random_value); return 0; } 

您可以按时间播种(在所有调用rand之前一次),如下所示:

 #include  // ... srand (time ( NULL)); 

使用此function,您可以根据需要设置最小值/最大值。

 #include  #include  /* generate a random floating point number from min to max */ double randfrom(double min, double max) { double range = (max - min); double div = RAND_MAX / range; return min + (rand() / div); } 

来源: [已解决] Ubuntu论坛中的 随机双生成器问题(C编程)

然后你会这样称呼它:

 double myRand = randfrom(-1.0, 1.0); 

但请注意,这很可能无法涵盖double的全部精度。 在没有考虑指数的情况下,IEEE-754 双精度包含52位有效数(即非指数部分)。 由于rand返回0RAND_MAX之间的int ,因此RAND_MAX的最大可能值为INT_MAX 。 在许多(大多数?)平台上, int是32位,因此INT_MAX0x7fffffff ,覆盖31位范围。

我认为创建一个真正的随机双精度的最好方法是使用它的结构。 这是一篇关于如何存储浮点数的文章。 如您所见,浮点数在1和-1之间的唯一限制条件是指数值不超过128。

Ieee754SingleDigits2Double将0和1的字符串转换为float变量并返回它。 我是从这个问题的答案得到的。

 #include  #include  #include  double Ieee754SingleDigits2Double(const char s[32]) { double f; int sign, exp; unsigned int mant; int i; sign = s[0] - '0'; exp = 0; for (i = 1; i <= 8; i++) exp = exp * 2 + (s[i] - '0'); exp -= 127; if (exp > -127) { mant = 1; // The implicit "1." exp -= 23; } else { mant = 0; exp = -126; exp -= 23; } for (i = 9; i <= 31; i++) mant = mant * 2 + (s[i] - '0'); f = mant; while (exp > 0) f *= 2, exp--; while (exp < 0) f /= 2, exp++; if (sign) f = -f; return f; } 

这是主要function:

 int main(void) { srand ( time ( NULL)); int i; char s[33]; for(i = 0; i < 32; i++) { if(i == 1) continue; s[i] = rand() % 2 + '0'; } s[1] = '0'; s[32] = 0; printf("%s\n", s); printf("%+g\n", Ieee754SingleDigits2Double(s)); return 0; } 

与其他答案类似,通过一些改进,您可能需要保持代码更安全和连贯:

 #include  /* srand and rand */ #include  /* getpid */ #include  /* time */ #include  /* errno */ #include  /* NAN */ /* generate a float random number in a range */ float randmm(float min, float max) { static int first = -1; if((first = (first<0))) srand(time(NULL)+getpid()); if(min>=max) return errno=EDOM, NAN; return min + (float)rand() / ((float)RAND_MAX / (max - min)); } 

仔细阅读我们的代码:

  • 一个静态变量first保证你不会忘记为伪随机数生成器(PRNG)播种。 逻辑简单而优雅:在第一次调用中, first是-1,然后将其比较为小于零,将其更新为true (值1)。 第二个调用询问first ,现在是1,是否小于零,这是 (值0),因此不调用srand() 。 他们说,第三个是魅力,所以现在first ,它是0,被问到它是否小于零,这对于这个和下一个迭代都是假的。
  • 接下来,您可能需要保证min-max不为零,否则您将得到一个令人讨厌的除以零(或NAN)。 为此,我们将明确地导致正确的错误。 使用errno.h设置错误, math.h使NAN (非数字)宏可用。 不建议比较两个浮点数是否相等(如if(min==max) ),因此在min更大的情况下尝试反转最小值/最大值并不是一个好主意,并且如果它们有第三个选项则不是是平等的。 只需两个选项即可简化您的if :它是正确的,或者不是。
  • 最后,我更喜欢使用float而不是double来对这个函数可以生成的内容不太信任。 32位整数(即RAND_MAX )只能做这么多。 对于所有位,填充float是合理的。 float的数字只有23位,而指数只有8位。 如果你使用double你会误导和过度自信这个function。 如果需要真双,请考虑使用/dev/urand或其他适当的真随机数生成器 (TRNG)。
  • 最后一行,即返回,只是一个简单的等式。 我想你可以轻松搞清楚。 我只是想明确地转换为float所以除了编译器的解释之外我还能看到代码的意图。
  • 当然,要用作OP想要的,只需调用float x = randmm(-1.0, 1.0);

经过大量搜索并从中获取提示后,我创建此函数以生成特定范围内的随机双数。

 #include  #include  #include  #include  double random(double min, double max) { //used it to generate new number each time srand( (unsigned int) time(NULL) ); double randomNumber, range , tempRan, finalRan; //generate random number form 0.0 to 1.0 randomNumber = (double)rand() / (double)RAND_MAX; //total range number from min to max eg. from -2 to 2 is 4 //range used it to pivot form -2 to 2 -> 0 to 4 for next step range = max - min //illustrate randomNumber to range //lets say that rand() generate 0.5 number, thats it the half //of 0.0 to 1.0, show multiple range with randomNumber we get the //half in range. eg 4 * 0.5 = 2 tempRan = randomNumber * range; //add the min to tempRan to get the correct random in ours range //so in ours example we have: 2 + (-2) = 0, thats the half in -2 to 2 finalRan = tempRan + min; return finalRan; } 

这是在说明我们范围内随机数的比率%。

这可能不是一个好主意,但仅仅因为它有效,这里有一种方法可以生成-1和1之间的随机双/dev/urandom ,包括使用/dev/urandomcos()

 #include  #include  #include  #include  #include  #include  int main() { int fd; double x; fd = open("/dev/urandom", O_RDONLY); if (fd == -1) return (1); read(fd, &x, sizeof(x)); close(fd); x = cos(x); printf("%f\n", x); return (0); }