【问题标题】:Generate Float Random Values (also negative)生成浮点随机值(也是负数)
【发布时间】:2011-12-04 19:06:53
【问题描述】:

如何在 C 中生成浮点随机值? (也是负面的

【问题讨论】:

  • 到目前为止你有什么?
  • 我刚刚生成了0到x的值...不是负数
  • 您想要 C 还是 C++ 答案?它们可能非常不同。请删除不相关的标签。
  • 你说得对,我需要一个 C 答案!我也调整了标签!
  • @Zany-Present 或展示您到目前为止所做的事情?不要只是在其中发布问题而不显示您之前尝试过的内容。将其作为建议

标签: c random


【解决方案1】:

一般来说,要从任意分布生成随机数,您首先要生成均匀随机数,然后将它们传递给累积分布函数的逆函数。

例如,假设您想要在区间 [-10.0, 10.0] 上均匀分布的随机数,而您得到的只是来自 [0.0, 1.0] 的随机数。 [-10.0, 10.0] 上均匀分布的累积分布函数为:

cdf(x) = 0.05 * x + 0.5   for x in [-10.0, 10.0]

这表示生成的随机数小于 x 的概率。倒数是

icdf(y) = 20.0 * y - 10.0   for y in [0.0, 1.0]

(您可以通过切换 x 和 y 轴在纸上轻松获得)。

因此要获得均匀分布在 [-10.0, 10.0] 上的随机数,您可以使用以下代码:

#include <stdlib.h>

// Returns uniformly distributed random numbers from [0.0, 1.0].
double uniform0to1Random() {
    double r = random();
    return r / ((double)RAND_MAX + 1);
}

// Returns uniformly distributed random numbers from [-10.0, 10.0].
double myRandom() {
  return 20.0 * uniform0to1Random() - 10.0;
}

事实上,您不需要 uniform0to1Random(),因为已经有很多来自 [0.0, 1.0] 的好的统一随机数生成器(例如在 boost 库中)。

您可以使用该方法生成具有几乎任何您想要的概率分布的随机数,方法是对如上所示的逆累积分布进行采样。

更多详情请见http://en.wikipedia.org/wiki/Inverse_transform_sampling

【讨论】:

  • 制作 srand((signed)time(NULL)); //通常是无符号的
【解决方案2】:

以下将为您提供介于 -max/2+max/2 之间的浮点数:

float max = 5000;
float r = max * ((float)rand()/(float)RAND_MAX - 0.5);

【讨论】:

  • 它将有一个非常奇怪的分布,分子中有常数,分母中有函数结果......
  • 谢谢,现在应该看起来更好了。
  • 非常好 - 除了它可能会影响您错过 floatdouble 的精度,具体取决于 RAND_MAX 值。由于不能保证它是 2 的幂,因此最好在此处也使用 double(尾数 52+1 而不是仅 23+1 位)resp。通常在这里使用double,以免失去任何精度。尽管如此,rand()RAND_MAX 的一个演员应该就足够了 - 然后另一个操作数恰好被这个接受了。
【解决方案3】:

编辑因为该问题仅针对 C 进行了编辑:

这个页面很有帮助:http://www.geekpedia.com/tutorial39_Random-Number-Generation.html

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

//use this first function to seed the random number generator, 
//call this before any of the other functions 
void initrand() 
{ 
    srand((unsigned)(time(0))); 
} 

//generates a psuedo-random float between 0.0 and 0.999... 
float randfloat() 
{ 
    return rand()/(float(RAND_MAX)+1); 
} 

//generates a psuedo-random float between 0.0 and max 
float randfloat(float max) 
{ 
    return randfloat()*max; 
} 

//generates a psuedo-random float between min and max 
float randfloat(float min, float max) 
{ 
    if (min>max) 
        return randfloat()*(min-max)+max;     
    else 
        return randfloat()*(max-min)+min; 
} 

//generates a psuedo-random double between 0.0 and 0.999... 
double randdouble() 
{ 
    return rand()/(double(RAND_MAX)+1); 
} 

//generates a psuedo-random double between 0.0 and max 
double randdouble(double max) 
{ 
    return randdouble()*max; 
} 

//generates a psuedo-random double between min and max 
double randdouble(double min, double max) 
{ 
    if (min>max) 
        return randdouble()*(min-max)+max;     
    else 
        return randdouble()*(max-min)+min; 
} 

int main()
{
    for (int i=0; i<10; i++)
        printf("%f\n", randdouble(-1,3));
}

输出样本:

2.360751
0.577532
2.132397
2.193760
2.646589
-0.209795
0.340891
2.072918
0.111099
1.215880

(注意范围:-1..3)

【讨论】:

  • @AndrejsCainikovs: were the tags。 C++ 几乎从来都不是纯 C
  • 不了解 C++。在 C 中,当 double 可以做同样的事情时,使用 float 通常是错误的:-)
【解决方案4】:

GNU 科学库有一些方法。

http://www.gnu.org/s/gsl/manual/html_node/Random-number-generator-algorithms.html

即使您由于许可而无法使用它,它也应该为您提供一些谷歌的名字。

boost 随机库 (C++) 对双精度和浮点数使用滞后斐波那契和 ranlux 算法,因此它们可能是您的另一种选择。 (方法不是 boost 库,因为它是 C++)

这些技术通常会在 0 -- 1 范围内为您提供结果。通过使用 R = rmin + v* (rmax-rmin) 其中 v 在 0 -- 1 中,您将在 rmin -- rmax 中得到 R

【讨论】:

    【解决方案5】:

    看看Boost.Random:

    http://www.boost.org/doc/libs/1_47_0/doc/html/boost_random.html

    您可以通过这种方式获得浮点随机值:

    boost::mt19937 base_rng;
    boost::uniform_01<> u01;
    boost::variate_generator<boost::mt19937&, boost::uniform_01<> > rng(base_rng, u01);
    
    rng(); // draws a random number
    

    请注意,新 C++ 标准现在提供随机数生成工具:

    http://gcc.gnu.org/onlinedocs/libstdc++/latest-doxygen/a01617.html

    【讨论】:

    • Boost 是 C++。问题是关于 C 的。
    • @glglgl 另一方面,C++ 标签的存在具有误导性。
    • 真的吗?说真的,这个问题也带有 c++ 标签,所以请在投票前检查所有内容!
    • 开箱即用,boost.random 生成随机整数。您没有展示如何使用它来生成随机浮点数。
    • 该问题在被问到后被重新标记。不幸的是,许多人错误地应用了both C/C++ 标签,以便将他们的问题呈现给更多的观众。
    【解决方案6】:

    你可以使用

    rand() / (double)RAND_MAX /* 0 <= random number <= 1 */
    rand() / (RAND_MAX + 1.0) /* 0 <= random number < 1 */
    

    用于 0 到 1 之间的随机数。
    然后乘以您想要的范围并添加初始值。

    比如获取随机数0 &lt;= X &lt; 4.2

    double tmp = rand() / (RAND_MAX + 1.0)
    X = tmp * 4.2;
    

    获取随机数-21.1 &lt;= X &lt;= 37.5

    double tmp = rand() / (double)RAND_MAX
    X = tmp * (37.5 + 21.1);
    X = X - 21.1;
    

    【讨论】:

      【解决方案7】:

      我知道的最简单的方法:

      int randNum = rand();
      float floatRand = randNum/RAND_MAX;
      

      floatRand 是 [0,1] 中的随机浮点数。但是,这种方法的分辨率受限于 RAND_MAX..

      [编辑]: 要获得负值,请生成另一个随机数,如果它大于 RAND_MAX/2,则将前者乘以 (-1)。

      【讨论】:

      • 谢谢,但我需要算法生成负值的可能性...
      • -1: randNumint 类型; RAND_MAX"integer constant expression" 相同。将第一个除以第二个将总是计算为0
      【解决方案8】:

      这将生成随机[任何可表示的浮点数]:

      #include <stdio.h>
      
      float randfdev(void)
          {
          float tmp;
          int fd = open("/dev/urandom",O_RDONLY);
          read(fd,&tmp,sizeof tmp);
          return tmp;
          }
      

      注意:

      • 没有错误检查
      • 假定为 IEEE 浮点,但其他格式也可以使用
      • 将产生 NaN、次正规、无穷大等

      【讨论】:

        猜你喜欢
        • 2010-10-15
        • 1970-01-01
        • 1970-01-01
        • 2011-06-28
        • 2023-01-03
        • 2021-11-12
        • 1970-01-01
        • 2013-12-19
        相关资源
        最近更新 更多