2012-04-07 23 views
4

このコードは、1回目の投げで200回連続してrに対して1つの結果を生成しました。後のトーゼは静的ではありません。彼らは変わります。どのようなアイデア私は何をねじ込んだ? Xcodeの使用。ありがとう!c初心者rand()

#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; 
} 
+3

[Dilbertあり](http://search.dilber t。com/comic /ランダム%20Nine):-) – kay

+0

あなたの問題は何ですか? –

+0

100回以上実行すると、1回目の投げは頭で起こります。その出来事のオッズは信じられないほど小さいですので、私はどこかに問題があると仮定しています...私は以前の実行と、すべての第一投げに加えて、コマンドラインから、ではないのXcodeから30回、それを実行した は頭でした。 – sheddd

答えて

4

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

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

あなたが見ることができるように、ランダムな値がシード値に基づいて計算(と新しいシード値が計算されます)され、我々は、これらの数字は、擬似ランダム呼ぶ理由、thatsの。とでテストを実行することができます今

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

とを:我々は最初の実行でinterstedているので、コードを少し簡略化することができます、最初のランドを()入力シードを取る関数を記述し、返すことができますこの機能:

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回の実行の間に多くの値を変更する必要がある場合は、その上で何らかの操作を行います)。

+0

うわー;ありがとう!ランドは複雑です:) – sheddd

+1

注これは 'ランド()'のただ一つの可能​​な実装であること。 C標準はサンプル実装を提供しますが、その使用を必要としません。 –

+0

LinuxまたはOS Xの場合、 '/ dev/urandom'でシードするのは簡単です。 –

1

おそらく、テストはスクリプト化されていて、実行可能な速度で実行されます。

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

擬似乱数ジェネレータには、現在のタイムスタンプ(1秒の分解能)が設定されています。

LinuxまたはBSDの/dev/urandom/などの他のエントロピーソースを調べることができます。 x86/x64システムでコードを実行する場合は、time stamp counterもエントロピーソースとして使用できます。

+0

私は手動で1回ずつ実行しました... 1回ごとに~3秒かかりました。 ありがとうございます。私はあなたのリンクを見ていきます! – sheddd

3

Windows(ここではワインでシミュレートされます)とglibc(x86_64)のバージョンは完全に異なりますが、コードはどちらの場所でもコンパイルされます。あなたのコードは私のLinuxマシンではうまくいきますが、今日、Windowsのバージョンのコードでは、時刻(NULL)から生成されたシードを使用すると、最初のロールでは私のために常に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のバージョンは、より多くの方法をtightly-これはRAND_MAXの32767に比べて非常に低い結果を返します。

+0

奇妙な;ありがとう!奇妙な。 – sheddd