在使用Apple Xcode时,下面的C程序将始终返回y的5,而z将返回一个随机数,即使它们有相同的表达式。你能找出这种行为的原因吗?

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

int main()
{
    int x,y,z;
    srand((unsigned int)time(NULL));
    x = ((unsigned int)time(NULL));
    y=((double)rand()/(double)(RAND_MAX)*10);
    z=((double)rand()/(double)(RAND_MAX)*10);
    printf("Time %d\n", x);
    printf("\n");
    printf("Number y %d\n", y);
    printf("\n");
    printf("Number z %d\n", z);
    printf("\n");
    return 0;
}

最佳答案

rand-31
以下是对您的程序的改编,它将更详细地显示正在发生的事情:

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

int main(void)
{
    int x = ((unsigned int)time(NULL));
    srand((unsigned int)x);
    int r1 = rand();
    int y  = ((double)r1/(double)(RAND_MAX)*10);
    int r2 = rand();
    int z  = ((double)r2/(double)(RAND_MAX)*10);
    printf("Time %d\n", x);
    printf("Random 1: %d\n", r1);
    printf("Number y: %d\n", y);
    printf("Random 2: %d\n", r2);
    printf("Number z: %d\n", z);
    return 0;
}

它捕获两个独立于计算的rand()调用的结果,以便可以打印它们。它还确保传递给time()的值与打印的值相同,尽管它们不同的可能性很小。
当我运行了几次之后,我得到了输出:
Time 1508694677
Random 1: 1292016210
Number y: 6
Random 2: 1709286653
Number z: 7

Time 1508694685
Random 1: 1292150666
Number y: 6
Random 2: 1821604998
Number z: 8

Time 1508694701
Random 1: 1292419578
Number y: 6
Random 2: 2046241688
Number z: 9

Time 1508694841
Random 1: 1294772558
Number y: 6
Random 2: 790587255
Number z: 3

如您所见,rand()返回的值不同,但差别不大,因此计算出的值并没有那么大差别。
rand-23
一个简单的升级选项是使用drand48()函数,如下所示:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main(void)
{
    int x = ((unsigned int)time(NULL));
    srand48((unsigned int)x);
    int r1 = lrand48();
    int y  = ((double)r1/(double)(RAND_MAX)*10);
    int r2 = lrand48();
    int z  = ((double)r2/(double)(RAND_MAX)*10);
    printf("RAND_MAX: %d\n", RAND_MAX);
    printf("Time:     %d\n", x);
    printf("Random 1: %d\n", r1);
    printf("Number y: %d\n", y);
    printf("Random 2: %d\n", r2);
    printf("Number z: %d\n", z);
    return 0;
}

代码打印RAND_MAX主要是为了显示它与lrand48()返回的值的范围兼容,而rand-13返回的值的范围是0..231-1。
这会产生不同的、可以说是更好的结果:
RAND_MAX: 2147483647
Time:     1508695069
Random 1: 705270938
Number y: 3
Random 2: 1758232243
Number z: 8

RAND_MAX: 2147483647
Time:     1508695074
Random 1: 1465504939
Number y: 6
Random 2: 733780153
Number z: 3

RAND_MAX: 2147483647
Time:     1508695080
Random 1: 1948289010
Number y: 9
Random 2: 1222424564
Number z: 5

arc4random()
或者,您也可以按照macOS文档的说明进行操作,然后切换到arc4random_uniform()。链接指向“遗留”XCode 5文档,但功能最近没有更改。
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main(void)
{
    int x = ((unsigned int)time(NULL));
    int r1 = arc4random_uniform(INT_MAX);
    int y  = ((double)r1/(double)(RAND_MAX)*10);
    int r2 = arc4random_uniform(INT_MAX);
    int z  = ((double)r2/(double)(RAND_MAX)*10);
    printf("INT_MAX:  %d\n", INT_MAX);
    printf("RAND_MAX: %d\n", RAND_MAX);
    printf("Time:     %d\n", x);
    printf("Random 1: %d\n", r1);
    printf("Number y: %d\n", y);
    printf("Random 2: %d\n", r2);
    printf("Number z: %d\n", z);
    return 0;
}

这将使用srand()在0..INT_MAX范围内生成一个值,该范围与生成的其他函数相同。没有类似于arc4random()的功能家族。
示例运行:
INT_MAX:  2147483647
RAND_MAX: 2147483647
Time:     1508695894
Random 1: 938614006
Number y: 4
Random 2: 851262647
Number z: 3

INT_MAX:  2147483647
RAND_MAX: 2147483647
Time:     1508695900
Random 1: 1332829945
Number y: 6
Random 2: 386007903
Number z: 1

INT_MAX:  2147483647
RAND_MAX: 2147483647
Time:     1508695913
Random 1: 1953583540
Number y: 9
Random 2: 1273643162
Number z: 5

rand-83
注意,如果您想要一个介于0和10之间的随机整数,那么您应该直接使用arc4random_uniform(10),而不是进行计算。
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main(void)
{
    int x = ((unsigned int)time(NULL));
    int y = arc4random_uniform(10);
    int z = arc4random_uniform(10);
    printf("Time:     %d\n", x);
    printf("Number y: %d\n", y);
    printf("Number z: %d\n", z);
    return 0;
}

示例输出:
Time:     1508696162
Number y: 5
Number z: 3

Time:     1508696163
Number y: 7
Number z: 5

Time:     1508696165
Number y: 3
Number z: 8

当我设法在一秒钟内运行程序3次时,arc4random()等的另一个优点就显示出来了。对于其他生成器,由于使用了相同的种子,这些生成器将产生相同的结果。
$ rand-83;rand-83;rand-83
Time:     1508696213
Number y: 4
Number z: 0
Time:     1508696213
Number y: 0
Number z: 1
Time:     1508696213
Number y: 9
Number z: 6
$

$ rand-31;rand-31;rand-31
Time 1508696334
Random 1: 1319865409
Number y: 6
Random 2: 1619339200
Number z: 7
Time 1508696334
Random 1: 1319865409
Number y: 6
Random 2: 1619339200
Number z: 7
Time 1508696334
Random 1: 1319865409
Number y: 6
Random 2: 1619339200
Number z: 7
$

JFTR:在运行macOS High Sierra 10.13的MacBook Pro上编译的代码。我使用GCC 7.2.0(而不是XCode 9)进行编译,但是系统库-而且它是这里的关键库。

关于c - Xcode中rand()的奇怪行为,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/46877089/

10-11 15:20