3

此代码连续 1 次折腾 200 次为 r 生成 1 结果;后来的投掷不是静态的;他们改变了;知道我搞砸了什么吗?使用 Xcode。谢谢!

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define tprop .5    // propability coin will be tails

int main(int argc, const char *argv[])
{
    int i;          // for loop counter
    int n;          // # of rolls
    int hc = 0;     // heads counter
    int tc = 0;     // tails counter
    int r;          // roll... 1=heads, 0=tails

    srand(time(NULL));  // seed Random# generator with current time

    printf("Enter # of times to toss a coin: ");
    scanf("%i", &n);

    for (i = 0; i < n; i++) {
        if ((float) rand() / RAND_MAX > tprop) {
            r = 1;
            hc++;
        } else {
            r = 0;
            tc++;
        }
        printf("%in", r);
    }
    printf("# of times heads came up: %i (%f%%)n", hc, (float) hc / n * 100);
    printf("# of times tails came up: %i (%f%%)n", tc, (float) tc / n * 100);

    return 0;
}
4

3 回答 3

4

To answer this question, first we need to look at rand() code.

From Rand Implementation:

void __cdecl srand (unsigned int seed)
{
    #ifdef _MT
        _getptd()->_holdrand = (unsigned long)seed;
    #else /* _MT */
        holdrand = (long)seed;
    #endif /* _MT */
}

int __cdecl rand (void)
{
   #ifdef _MT
    _ptiddata ptd = _getptd();
    return( ((ptd->_holdrand = ptd->_holdrand * 214013L + 2531011L) >> 16) &
    0x7fff );
   #else /* _MT */
    return(((holdrand = holdrand * 214013L + 2531011L) >> 16) & 0x7fff);
   #endif /* _MT */
}

As you can see, the random value is computed based on the seed value (and a new seed value is the computed), thats why we call those numbers pseudo-random. Since we are intersted in the first run, lets simplify the code a bit, lets write a function which takes the input the seed, and return the first rand():

int firstRand(unsigned int seed) {
    return (((seed * 214013L + 2531011L) >> 16) & 0x7fff);
}

And now lets run a test with with this function:

for (i = 0; i < 50; ++i) {
    printf("seed = %u; rand = %d\n", seed + i, firstRand(seed + i));
}

Here I got this result:

seed = 1333783311; rand = 19779
seed = 1333783312; rand = 19783
seed = 1333783313; rand = 19786
seed = 1333783314; rand = 19789
seed = 1333783315; rand = 19792
seed = 1333783316; rand = 19796
seed = 1333783317; rand = 19799
seed = 1333783318; rand = 19802
seed = 1333783319; rand = 19805
seed = 1333783320; rand = 19809
seed = 1333783321; rand = 19812
seed = 1333783322; rand = 19815
seed = 1333783323; rand = 19819
seed = 1333783324; rand = 19822
seed = 1333783325; rand = 19825
seed = 1333783326; rand = 19828
seed = 1333783327; rand = 19832
seed = 1333783328; rand = 19835
seed = 1333783329; rand = 19838
seed = 1333783330; rand = 19841
seed = 1333783331; rand = 19845
seed = 1333783332; rand = 19848
seed = 1333783333; rand = 19851
seed = 1333783334; rand = 19854
seed = 1333783335; rand = 19858
seed = 1333783336; rand = 19861
seed = 1333783337; rand = 19864
seed = 1333783338; rand = 19868
seed = 1333783339; rand = 19871
seed = 1333783340; rand = 19874
seed = 1333783341; rand = 19877
seed = 1333783342; rand = 19881
seed = 1333783343; rand = 19884
seed = 1333783344; rand = 19887
seed = 1333783345; rand = 19890
seed = 1333783346; rand = 19894
seed = 1333783347; rand = 19897
seed = 1333783348; rand = 19900
seed = 1333783349; rand = 19903
seed = 1333783350; rand = 19907
seed = 1333783351; rand = 19910
seed = 1333783352; rand = 19913
seed = 1333783353; rand = 19917
seed = 1333783354; rand = 19920
seed = 1333783355; rand = 19923
seed = 1333783356; rand = 19926
seed = 1333783357; rand = 19930
seed = 1333783358; rand = 19933
seed = 1333783359; rand = 19936
seed = 1333783360; rand = 19939

So, as you can see, if the seed are close, the values will probably be close to, and since you used the current time, the 200 tests you ran were all with seed values close to each other.

time(NULL) return the current time in seconds. To get better results you should use the time in milliseconds (and if you really need the values to change a lot between 2 runs do some operation over it).

于 2012-04-07T07:28:21.330 回答
3

rand 的 Windows(这里用 wine 模拟)和 glibc (x86_64) 版本完全不同,但代码将在任何地方编译。你的代码在我的 Linux 机器上运行良好,但是今天,在这个小时,当使用从 time(NULL) 生成的种子时,你的代码的 Windows 版本总是在第一轮为我返回 1——即使我等待了几分钟。也许几个小时、几天、几个月之后会有所不同。看一下这个:

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

int main (int argc, const char *argv[]) {
    int i;
    int r;
    printf ("rand() returns:\n",RAND_MAX);
    for (i = 0; i < 25; i++) {
        srand (i);
        r = rand();
        printf ("%i ", r);
    } printf ("\nout of RAND_MAX of %li\n",RAND_MAX);
    return 0;
} 

Linux (x86_64) 上的结果:

rand() returns:
1804289383 1804289383 1505335290 1205554746 1968078301 590011675 290852541 1045618677 757547896 444454915 1215069295 1989311423 1687063760 1358590890 2146406683 762299093 462648444 1227918265 1995168598 623271449 319571911 1086411056 1857631170 1562469902 188364873 
out of RAND_MAX of 2147483647

葡萄酒的结果(用 mingw 编译):

rand() returns:
38 41 45 48 51 54 58 61 64 68 71 74 77 81 84 87 90 94 97 100 103 107 110 113 116 
out of RAND_MAX of 32767

请注意 Windows 版本如何与种子值更紧密地耦合,因此与 32767 的 RAND_MAX 相比,它返回​​的结果非常低。

于 2012-04-07T08:10:56.737 回答
1

可能您的测试是脚本化的,并且运行速度尽可能快。

所以大多数测试将在同一时间秒内执行。

您使用当前时间戳为伪随机数生成器播种,其分辨率为一秒。

您可以查看其他熵源/dev/urandom/,例如 Linux 或 BSD。如果您在 x86/x64 系统上运行代码,您也可以使用时间戳计数器作为熵源。

于 2012-04-07T07:21:55.493 回答