【问题标题】:clarification for RAND_MAX and rand() in c stdlib.hc stdlib.h 中 RAND_MAX 和 rand() 的说明
【发布时间】:2019-02-02 16:31:14
【问题描述】:

当 RAND_MAX 的值似乎是 0.000000 时,为什么以下 c 代码只为 double a,b 生成介于 0 和 1 之间的实数(例如:0.840188,0.394383...等)。 RAND_MAX 不应该为rand() 函数生成的数字设置最大值吗?

    #include <stdio.h>
    #include <stdlib.h>
    int main()
    {

    double a,b,c;
    for (int i=0;i<100;i++){
    a=(double)rand()/(double)RAND_MAX;
    b=(double)rand()/(double)RAND_MAX;
    c=a-b;
    printf("itteration : %d values a=%f,b=%f,c=%f, RAND_MAX=%f \n",i,a,b,c,RAND_MAX);
    }  
    return 0;
    }

【问题讨论】:

  • 如果 x 介于 0 和 max 之间,x / max 的结果将始终介于 0 和 1 之间,即简单的数学运算。加上RAND_MAX 不是双精度整数,所以使用 %d 使用 printf 打印它。 rand 不适合生成双数,它是为 int 数设计的,它不是很“随机”。您应该搜索在 C 中处理随机数的库。

标签: c gnu ansi ansi-c


【解决方案1】:

...RAND_MAX 的值似乎是 0.000000。

您正在使用双精度说明符打印一个整数。这是未定义的行为。

来自 C99 标准 (N1256)。

7.19.6.3 printf 函数
...
2. printf 函数等价于 fprintf 插入参数 stdout 在 printf 的参数之前。

7.19.6.1 fprintf 函数
....
9. 如果转换规范无效,则行为未定义。 如果有任何参数 不是相应转换规范的正确类型,行为是 未定义。

所以它为RAND_MAX 打印0.000。你的另一个问题:

RAND_MAX 不应该为 rand() 函数生成的数字设置最大值吗?

rand() 返回一个在0RAND_MAX 范围内的伪随机数。 RAND_MAX 是一个常量,其默认值可能因实现而异,但至少被授予32767

rand()RAND_MAX 的浮点除法将产生一个介于01 之间的值。

【讨论】:

    【解决方案2】:

    RAND_MAX 是一个整数常量,但您使用 %f 说明符(用于 double)打印它,这是未定义的行为(在您的情况下恰好打印 0)。使用%d,您将看到RAND_MAX 的实际值。

    顺便说一句,如果您将警告调得足够高,几乎所有体面的编译器都会警告您有关无效的printf。确保这样做,C 和 C++ 的陷阱足够多,至少让编译器在可能的时候帮助你。

    【讨论】:

    • 啊,是的,谢谢!但快速查看源代码显示#define RAND_MAX 2147483647 但 RAND_MAX 没有定义为整数,只是一个没有类型的立即值。编译器是否采用立即值并默认将其分配为整数类型?
    • @TheSprintingEngineer a #define 创建一个宏,这是一种残酷的文本替换,所以无论何时你写RAND_MAX 就像你写2147483647 一样;现在,这个值是一个十进制整数文字 - 因为它匹配相应的语法产生,即[1-9][0-9]*。十进制整数表达式的类型是通过标准中详述的算法决定的,其本质上类似于“获取解析的数字并尝试将其放入intunsigned intlongunsigned longlong long ,unsigned long long;第一个能代表它的,就是它的类型”。
    • 顺便说一句,有趣的是,标准要求 RAND_MAX 只是一个“常量整数表达式”,它对其特定的整数类型没有任何限制,所以理论上实现可能有一个#define RAND_MAX 32767ULL(即unsigned long long文字);因此,为了获得最大的便携性,在打印时应该首先将其转换为int,否则%d 说明符可能不正确(OTOH 没有溢出的风险,因为RAND_MAX 是@987654344 的最大值@ 可以返回,它返回一个int,所以它肯定适合)。
    猜你喜欢
    • 1970-01-01
    • 2015-02-26
    • 2013-12-16
    • 1970-01-01
    • 1970-01-01
    • 2019-01-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多