3

このコードは、200回続けて1回目のトスで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

この質問に答えるには、最初にrand()コードを調べる必要があります。

ランドの実装から:

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 */
}

ご覧のとおり、ランダム値はシード値に基づいて計算されます(そして、新しいシード値が計算されます)。そのため、これらの数値を疑似ランダムと呼びます。最初の実行に関心があるので、コードを少し単純化し、入力をシードとして受け取る関数を記述し、最初のrand()を返します。

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

そして今、この関数でテストを実行しましょう:

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

ここで私はこの結果を得ました:

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

したがって、ご覧のとおり、シードが近い場合、値はおそらく近くなります。現在の時刻を使用したため、実行した200のテストはすべて、シード値が互いに近いものでした。

time(NULL)は、現在の時刻を秒単位で返します。より良い結果を得るには、ミリ秒単位の時間を使用する必要があります(2回の実行の間で値を大幅に変更する必要がある場合は、それに対して何らかの操作を行います)。

于 2012-04-07T07:28:21.330 に答える
3

Windows(ここではwineでシミュレート)とglibc(x86_64)バージョンのrandは完全に異なりますが、コードはどちらの場所でもコンパイルされます。あなたのコードは私のLinuxボックスでうまく機能しますが、今日、この時間に、時間(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

おそらく、テストはスクリプト化されており、実行できる限り高速に実行されます。

したがって、ほとんどのテストは同じ実時間1秒以内に実行されます。

疑似乱数ジェネレーターに、1秒の解像度を持つ現在のタイムスタンプをシードします。

/dev/urandom/LinuxやBSDのような他のエントロピーソースを調べることができます。x86 / x64システムでコードを実行する場合は、タイムスタンプカウンターをエントロピーソースとして使用することもできます。

于 2012-04-07T07:21:55.493 に答える