如何在C中生成随机浮点数

Posted

技术标签:

【中文标题】如何在C中生成随机浮点数【英文标题】:How to generate random float number in C 【发布时间】:2012-11-04 17:30:57 【问题描述】:

我找不到任何解决方案来生成[0,a] 范围内的随机浮点数,其中a 是用户定义的某个浮点数。

我尝试了以下方法,但似乎无法正常工作。

float x=(float)rand()/((float)RAND_MAX/a)

【问题讨论】:

c-faq.com/lib/randrange.html 谢谢。应该是: float x=(float)rand()/(((float)RAND_MAX/a) 还是 float x=(float)rand()/((float)RAND_MAX/a+1) ? 投票决定重新打开 2 个副本 1) 专注于 C++ 解决方案 2) 专注于随机整数。 How to generate a random number in C?的可能重复 @rid nope,那个链接刚刚回到这里:-D 【参考方案1】:

试试:

float x = (float)rand()/(float)(RAND_MAX/a);

要了解其工作原理,请考虑以下内容。

N = a random value in [0..RAND_MAX] inclusively.

上面的等式(为了清楚起见去掉了演员表)变成了:

N/(RAND_MAX/a)

但是除以分数等于乘以分数的倒数,所以这相当于:

N * (a/RAND_MAX)

可以改写为:

a * (N/RAND_MAX)

考虑到N/RAND_MAX 始终是一个介于 0.0 和 1.0 之间的浮点值,这将生成一个介于 0.0 和 a 之间的值。

或者,您可以使用以下内容,它可以有效地完成我上面显示的细分。我实际上更喜欢这个,因为它更清楚实际发生的事情(无论如何对我来说):

float x = ((float)rand()/(float)(RAND_MAX)) * a;

注意:a 的浮点表示必须精确,否则这将永远不会达到a 的绝对边缘情况(它会接近)。有关原因的详细信息,请参阅this article。

示例

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

int main(int argc, char *argv[])

    srand((unsigned int)time(NULL));

    float a = 5.0;
    for (int i=0;i<20;i++)
        printf("%f\n", ((float)rand()/(float)(RAND_MAX)) * a);
    return 0;

输出

1.625741
3.832026
4.853078
0.687247
0.568085
2.810053
3.561830
3.674827
2.814782
3.047727
3.154944
0.141873
4.464814
0.124696
0.766487
2.349450
2.201889
2.148071
2.624953
2.578719

【讨论】:

这可能具有非常糟糕的舍入属性。 rand() 返回一个 32 位 int,您将其转换为 32 位浮点数,这将导致值被量化。例如,你得到值 1000000192 的可能性是值 1 的 64 倍,因为从 1000000161 到 1000000223 全部舍入到 1000000192。你可以通过转换为 double 来避免这种情况,然后在最后转换为 float :浮点((双)兰德()/(双)(RAND_MAX/a))。 在我看来,清除形式是 a * (N/RAND_MAX),因为 N/RAND_MAX 是 0 到 1 之间的随机数。 @GlennMaynard:如果你除以(RAND_MAX+1ULL)(大概是 2 的幂),你只是在缩放 FP 指数。一些舍入实际上是必要的:如果你想在 [0..1] 上生成 uniform 浮点值,但仍然有机会生成每个可表示的浮点,你需要多个整数值来舍入到相同范围的 0.5, 1 部分的最终浮点数。指数越小,每个可表示的浮点数越接近,这就是为什么你不能只使用rand 来生成 FP 位模式(不会是统一的)。 除非你只使用约 24 位熵,所以每一个可能的输出都是均匀分布的(例如生成 [1,2] 然后减去 1.0),每 1 次你得到一个非常小的数字,您需要多次获得 0.5, 1 范围内的数字,以使分布均匀。尽管如此,除以 RAND_MAX 而不是 RAND_MAX+1 可能意味着转换 rand -> double 会有一些好处或至少有所不同。 (使用 double,您可能有足够的精度来使用乘法逆而不是实际除法。)【参考方案2】:

您还可以在 [min, max] 范围内生成类似

float float_rand( float min, float max )

    float scale = rand() / (float) RAND_MAX; /* [0, 1.0] */
    return min + scale * ( max - min );      /* [min, max] */

【讨论】:

【参考方案3】:

虽然现在可能无关紧要,但这里有一个在 2 个值之间生成浮点数的函数。

#include <math.h>

float func_Uniform(float left, float right) 
    float randomNumber = sin(rand() * rand());
    return left + (right - left) * fabs(randomNumber);

【讨论】:

不错的技巧,也是唯一一个处理通过缩放随机数引入的量化 € [0..RAND_MAX] € |N。但是,两个随机数与正弦的乘积会导致分布不均匀。这可以以某种方式规避吗? math.stackexchange.com/questions/456250/…【参考方案4】:

这会在两个浮点数之间生成一个随机浮点数。

float RandomFloat(float min, float max)
   return ((max - min) * ((float)rand() / RAND_MAX)) + min;

【讨论】:

【参考方案5】:

如果您想在某个范围内生成随机浮点数,请尝试下一个解决方案。

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


float
random_float(const float min, const float max)

    if (max == min) return min;
    else if (min < max) return (max - min) * ((float)rand() / RAND_MAX) + min;

    // return 0 if min > max
    return 0;



int
main (const int argc, const char *argv[])

    srand(time(NULL));

    char line[] = "-------------------------------------------";

    float data[10][2] = 
        -10, 10,
        -5., 5,
        -1, 1,
        -0.25, -0.15,
        1.5, 1.52,
        -1700, 8000,
        -0.1, 0.1,
        -1, 0,
        -1, -2,
        1.2, 1.1
    ;

    puts(line);
    puts("     From    |    Result    |      To");
    puts(line);


    int i;
    for (i = 0; i < 10; ++i) 
        printf("%12f | %12f | %12f\n", data[i][0], random_float(data[i][0], data[i][1]), data[i][1]);
    

    puts(line);

    return 0;

结果(值变化无常)

-------------------------------------------
     From    |    Result    |      To
-------------------------------------------
  -10.000000 |     2.330828 |    10.000000
   -5.000000 |    -4.945523 |     5.000000
   -1.000000 |     0.004242 |     1.000000
   -0.250000 |    -0.203197 |    -0.150000
    1.500000 |     1.513431 |     1.520000
-1700.000000 |  3292.941895 |  8000.000000
   -0.100000 |    -0.021541 |     0.100000
   -1.000000 |    -0.148299 |     0.000000
   -1.000000 |     0.000000 |    -2.000000
    1.200000 |     0.000000 |     1.100000
-------------------------------------------

【讨论】:

以上是关于如何在C中生成随机浮点数的主要内容,如果未能解决你的问题,请参考以下文章

在C语言中,如何将一个浮点数变换成整数?

php随机浮点数都有哪些?比如从0.1到3.0中随机一个浮点数出来?

如何把浮点数转换成字符串?

C 语言 哪个函数可以把 浮点数转换成字符串 带小数点 怎么做

excel表格如何将十六进制转换成浮点数

C语言中如何对浮点数进行四舍五入?