none
甘デジのICカウンターのような動作 RRS feed

  • 質問

  •    

    #include <stdio.h>
    #include <stdlib.h>
    #include <string>
    #include <iostream>
    #include <cstdlib>
    #include <ctime>
    using namespace std;
    const int HI = 69000;
    #define rand_max 65536
    int main()


    {
     int on=0;
     int count=1;

     start:
     int i=1;
     int a=1;
     
     int ATbox[HI];
     char b;
     
     srand((unsigned int) time(0));

     cout <<"回転数"<<count  <<" "; cout << endl;

     cout <<"当選回数" <<on<<" "; cout << endl;

     while (i) {
      ATbox[HI]=1+ (int) (rand() * 10.0/(1.0 + RAND_MAX));
      cout <<  ATbox[HI]<<" ";
      
      
      
     cout << endl;
     --i;
     }
     
     if  (ATbox[HI] == 9)  { cout <<"魚群リーチ!!! 大当たり !ラッキースタート"<<endl;on++;}

     else if (ATbox[HI] == 10) { cout <<"魚群リーチ!!! 確変大当たり !スーパーラッキースタート"<<endl;on++;}


     cin >> b;
      count++;

     


     if(a=!0){ goto start;}
     return 0;


    }

     試行回数1回だと同じ乱数ばかり出力されます。

    2回以上だと 乱数が出力されます.

    当たり判定が無視されたり出力されたり いい加減な挙動を示します。

    又 試行回数2回以上だと 同時に当たりを2個引い場合 1個しか出力されません。

    どこが悪いのでしょうか?

    ご教授のほどよろしくお願いします。

    2013年6月9日 9:44

回答

  •  う~ん。。。まぁ、自分が作ったプログラムと対話するべきですね。何がしたいのでしょう?

    cout <<"回転数"<<count  <<" "; cout << endl;
    cout <<"当選回数" <<on<<" "; cout << endl;
    while (i) {
    

     while ブロックの外に「標準出力への出力」があるのですが、これだと何回繰り返そうが1回しか表示されないですよね。

    while (i) {
        ATbox[HI]=1+ (int) (rand() * 10.0/(1.0 + RAND_MAX));
        cout <<  ATbox[HI]<<" ";

     ここも難解ですね。i 回繰り返そうとしていますが、ATbox のインデックス HI にしか代入されません。他のエリアには、何が入るのでしょう?ATbox[HI] の使い方がまずいのは既出。

     rand 式も、不明です。rand は 0~32767 の整数値を返します。これを10倍して、65537 で割り、整数値にすると・・・6554以上の数でなければ、1になりません。約2割は0になります。これは、意図通りですか?(6553 * 10 / (1.0 + 65536) = 65530 / 65537 = 0.999 なので0となるため、6554未満の数は0)

     Azuleanさんの指摘で、上の1行を下のように訂正。

     rand 関数の戻り値を10倍して32768 で割るので、3277以上、ですね。約1割が (0 + 1) になり、1の出現率が高くなります。1~10を出したいなら、rand() % 10 + 1 で良いのでは?

    当たり判定が無視されたり出力されたり いい加減な挙動を示します。

     挙動がいい加減なのは、いい加減なコードを組んでいるからです。あなたがしたいことはなんでしょうか。プログラムというのは、したいことを実現するための手順を一つ一つ積み上げていくことです。あなたは、自分がしたいこと、コンピュータにさせたいことを、一つ一つ考えたでしょうか。この投稿からは、そのようには見えません。

     「当たり判定」とは、どれのことでしょうか。「ATbox[HI] == 9」のところでしょうか。もしそうなら、これが実行時にエラーにならないことがかなりラッキーなことです。というのは既出。ATbox 配列の中にある特定の回が特定の数になったときだけ当たりですが、それは意図通りでしょうか。(ここも修正)

     「試行回数1回だと同じ乱数ばかり」というのは、「srand((unsigned int) time(0)); でシードを設定しているのに」ということでしょうか。だとしたら、これがいつ実行されるか、というところを、よく見ましょう。コードの終わりの方までいって、a が 0 でないなら start ラベルに飛びます。srand を実行するのは start ラベルの下なので、またシードが設定されます。試行回数が1回なら、これくらいのコードなら100ミリ秒くらいで実行できるのではないでしょうか。すると、10回くらいは同じ結果になるでしょうね。

     というわけで、プログラムを作る上で大事なのは、自分がしたいことを、コンピュータという他人にきちんと説明することです。コンピュータは融通が利かないので、誤解のないように説明しなければなりません。1命令、1関数に相当するまで細かくかみ砕いて説明してあげてください。

    -----追加

    書いてる最中に投稿があった。

    「出力結果は、以下になります。」とありますが、コード中には「2回目」「3回目」という出力はしていません。書き換えたりせず、そのままを書いてください。


    Jitta@わんくま同盟

    2013年6月9日 13:25

すべての返信

  • オレオレ用語で説明せず、他者と意思疎通することを考えましょう。

    甘デジもICカウンターも何のことだかわかりません。
    # まぁ察しはつきますが。

    「当たり判定が無視されたり出力されたり」と抽象的に書かず、もっと具体的に、

    • どの行が
    • どういう動作を期待していたのか
    • それに対してどういう結果が得られたのか

    を記述してください。

    とりあえず、 ATbox[HI] は確保した配列の範囲からはみ出ています。

    2013年6月9日 10:43
  • パチンコ用語で話をする必然性はなく、単に疑似乱数の使い方と配列の使い方の問題でしょう。

    疑似乱数は真の意味の乱数ではありませんので、同じ seed で始めた場合、同じ数列が得られることになります。
    「試行回数 1 回だと同じ乱数ばかり出力されます」が、同じ 1 秒の間の話であればそんなものです。

    次に、あなたは「あたりを複数回発生した場合であっても一回しか出力しない」ようにコードを作っています。
    コードは作ったとおりにしか動かないので、何が繰り返されるのか、何が繰り返されないのかをきちんと理解するようにしてください。

    2013年6月9日 10:48
    モデレータ
  • #include <stdio.h>
    #include <stdlib.h>
    #include <string>
    #include <iostream>
    #include <cstdlib>
    #include <ctime>
    using namespace std;
    const int HI = 65600;
    #define rand_max 65536
    int main()


    {
     int on=0;
     int off=0;
     int count=1;
     int *p;
     start:
     int i=4;
     int a=1;
     
     int ATbox[HI];
     char b;
     
     srand((unsigned int) time(0));

     cout <<"回転数"<<count  <<" "; cout << endl;

     cout <<"大当たり回数" <<on<<" "; cout << endl;

     while (i) {
      ATbox[HI]=1+ (int) (rand() * 10.0/(1.0 + RAND_MAX));
      cout <<  ATbox[HI] <<" ";
      
      if  (ATbox[HI] == 9)  { cout <<"魚群リーチ!!! 大当たり !ラッキースタート"<<"当選回数"<<on++;}

     else if (ATbox[HI] == 10) { cout <<"魚群リーチ!!! 確変大当たり !スーパーラッキースタート"<<"当選回数"<<on++;}
      
     cout << endl;
     --i;
     }


     cin >> b;
      count++;


     if(a=!0){ goto start;}
     return 0;

    }

    いつもお世話になっております。

    ご回答ありがとうございます。

    デバッグモードで行を追いかけてみました。

      if  (ATbox[HI] == 9)  { cout <<"魚群リーチ!!! 大当たり !ラッキースタート"<<"当選回数"<<on++;}

     else if (ATbox[HI] == 10) { cout <<"魚群リーチ!!! 確変大当たり !スーパーラッキースタート"<<"当選回数"<<on++;}

    の部分が後になっておリました。

     int i=4; この部分で4個出力してますが

    1個目が常に同じ値です。後の3個は、変動して出力されます。

    出力結果は、以下になります。

    2回目

    3回目

    n

    n

    n

    というように 必ず1回目が 書き換えられないで メモリーされています。

    2013年6月9日 12:49
  •  う~ん。。。まぁ、自分が作ったプログラムと対話するべきですね。何がしたいのでしょう?

    cout <<"回転数"<<count  <<" "; cout << endl;
    cout <<"当選回数" <<on<<" "; cout << endl;
    while (i) {
    

     while ブロックの外に「標準出力への出力」があるのですが、これだと何回繰り返そうが1回しか表示されないですよね。

    while (i) {
        ATbox[HI]=1+ (int) (rand() * 10.0/(1.0 + RAND_MAX));
        cout <<  ATbox[HI]<<" ";

     ここも難解ですね。i 回繰り返そうとしていますが、ATbox のインデックス HI にしか代入されません。他のエリアには、何が入るのでしょう?ATbox[HI] の使い方がまずいのは既出。

     rand 式も、不明です。rand は 0~32767 の整数値を返します。これを10倍して、65537 で割り、整数値にすると・・・6554以上の数でなければ、1になりません。約2割は0になります。これは、意図通りですか?(6553 * 10 / (1.0 + 65536) = 65530 / 65537 = 0.999 なので0となるため、6554未満の数は0)

     Azuleanさんの指摘で、上の1行を下のように訂正。

     rand 関数の戻り値を10倍して32768 で割るので、3277以上、ですね。約1割が (0 + 1) になり、1の出現率が高くなります。1~10を出したいなら、rand() % 10 + 1 で良いのでは?

    当たり判定が無視されたり出力されたり いい加減な挙動を示します。

     挙動がいい加減なのは、いい加減なコードを組んでいるからです。あなたがしたいことはなんでしょうか。プログラムというのは、したいことを実現するための手順を一つ一つ積み上げていくことです。あなたは、自分がしたいこと、コンピュータにさせたいことを、一つ一つ考えたでしょうか。この投稿からは、そのようには見えません。

     「当たり判定」とは、どれのことでしょうか。「ATbox[HI] == 9」のところでしょうか。もしそうなら、これが実行時にエラーにならないことがかなりラッキーなことです。というのは既出。ATbox 配列の中にある特定の回が特定の数になったときだけ当たりですが、それは意図通りでしょうか。(ここも修正)

     「試行回数1回だと同じ乱数ばかり」というのは、「srand((unsigned int) time(0)); でシードを設定しているのに」ということでしょうか。だとしたら、これがいつ実行されるか、というところを、よく見ましょう。コードの終わりの方までいって、a が 0 でないなら start ラベルに飛びます。srand を実行するのは start ラベルの下なので、またシードが設定されます。試行回数が1回なら、これくらいのコードなら100ミリ秒くらいで実行できるのではないでしょうか。すると、10回くらいは同じ結果になるでしょうね。

     というわけで、プログラムを作る上で大事なのは、自分がしたいことを、コンピュータという他人にきちんと説明することです。コンピュータは融通が利かないので、誤解のないように説明しなければなりません。1命令、1関数に相当するまで細かくかみ砕いて説明してあげてください。

    -----追加

    書いてる最中に投稿があった。

    「出力結果は、以下になります。」とありますが、コード中には「2回目」「3回目」という出力はしていません。書き換えたりせず、そのままを書いてください。


    Jitta@わんくま同盟

    2013年6月9日 13:25
  • rand_max という小文字定数がややこしいですが、実際の分母は RAND_MAX(0x7FFF = 32767) であること、goto 文で繰り返しをされていることの 2 点にご注意ください。

    ただ、わかりづらいコードであること、srand を何度も実行する意味がないことは同意します。

    * 追記

    Visual C++ の rand 関数の実装を深く追っていませんが、毎回 time の戻り値で srand を実行していると、初回 rand は近い数値になるようなので「srand を何回もするのが悪い」という結論ですね。

    // ほかにも諸々、配列を使っている意味がないとかありますが。

    2013年6月9日 13:41
    モデレータ
  • #include <stdio.h>
    #include <stdlib.h>
    #include <string>
    #include <iostream>
    #include <cstdlib>
    #include <ctime>
    using namespace std;
    const int HI = 65600;
    #define rand_max 65536
    int main()


    {
     int on=0;
     int off=0;
     int count=1;
     int *p;

       start:
     p=new int[HI];
     int i=4;
     int a=1;
     
     
     char b;
     
     srand((unsigned int) time(0));

     cout <<"回転数"<<count  <<" "; cout << endl;

     cout <<"大当たり回数" <<on<<" "; cout << endl;

     

     while (i) {
      *p=1+ (int) (rand() * 198.0/(1.0 + RAND_MAX));
      cout <<  *p <<" ";
      
      if  (*p == 99)  { cout <<"魚群リーチ!!! 大当たり !ラッキースタート"<<"当選回数"<<on++;}

     else if (*p == 100) { cout <<"魚群リーチ!!! 確変大当たり !スーパーラッキースタート"<<"当選回数"<<on++;}
      
     cout << endl;
     --i;
     }


     cin >> b;
      count++;

     


     if(a=!0){ goto start;}
     return 0;


    }

     

     いつもお世話になっております。

    ご回答ありがとうございます。

    乱数の生成は、甘デジ実機に似せて作ろうと思いまして

    これは、2の16乗 65536 ÷ 656 99分の1 という甘デジのICカウンターの仕様を真似ようと

    思い できる限り簡単な物を考えました。 実際は、2の16乗を0.05秒以内 1周という規定がありますが

    皆そのように作られているようです。

    このルーレット部分を模擬するプログラムを考えてみたのですが 簡単にうまく動きません。 

    乱数の範囲は、0から21億4千程度あると聞いてます。vc++expは、32767なのかもしれません。

    もう少し 変えてみたりしてみます。 とりあえず動的メモリーを使用してみましたが 結果は、変わりませんでした。

    やはり4行出力するうちの1行目が常に同じ数値でした。

    2013年6月9日 14:26
  • もう一回書きますね。

    Visual C++ の rand 関数の実装を深く追っていませんが、毎回 time の戻り値で srand を実行していると、初回 rand は近い数値になるようなので「srand を何回もするのが悪い」という結論ですね。

    • 回答の候補に設定 佐祐理 2013年6月9日 22:42
    2013年6月9日 14:28
    モデレータ
  • goto startまでが1秒以内に行われたなら、 time(0) は同じ時刻、つまり同じ数値を返し、 srand() も同じ数値で初期化されます。

    プログラムは書かれた通りの動作をしています。

    • 回答の候補に設定 佐祐理 2013年6月9日 22:42
    2013年6月9日 14:29
  • いつもお世話になっております。

    ご回答ありがとうございます。

    デバックモードで10回程度 確認したところ

    確かに数値が変わるのを確認しました。

    お手数をおかけました。

        

    こちらで初期化する事で   srand((unsigned int)timeGetTime();1秒以内でも

    対応することができました。

    cout <<RAND_MAX<<endl;で確認したところVC++expressの乱数の最大値は、32767でした。

    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <iostream>

    #include <ctime>
    #include <random>
    #include <windows.h>
    #pragma comment(lib, "winmm.lib")


    using namespace std;
    const int HI = 65600;


    int main()


    {
     int on=0;
     int off=0;
     int count=1;
     int *p;
     int *pc;
     int min=0;
     int max;
       start:
     p=new int[HI];
     int i=4;
     int a=1;
     clock_t tt;
     int t;
     pc=new int;


     
     char b;


     tt=clock();
     
     srand((unsigned int)timeGetTime());
     
     *pc=timeGetTime();

     cout <<"回転数"<<count*4 <<" "; cout <<"前回大当たり回数"<< min*4 <<"";   cout << endl;

     cout <<"大当たり回数" <<on+off<<" "; cout << endl;

      cout <<"経過時間"<< tt/100  <<endl;
      cout <<"引数"<< *pc <<endl;

     while (i) {
      *p=1+ (int) (rand() * 7000.0/(1.0 + RAND_MAX));
      cout <<  *p <<" ";
      
      
      if  (*p == 99)  { cout <<"魚群リーチ!!! 大当たり !ラッキースタート"<<"当選回数"<<off++;min=count;}

     else if (*p == 100) { cout <<"魚群リーチ!!! 確変大当たり !スーパーラッキースタート"<<"当選回数"<<on++;min=count;}
     else if (*p == 200) { cout <<"魚群リーチ!!! 確変大当たり !スーパーラッキースタート"<<"当選回数"<<on++;min=count;}
     else if (*p == 300) { cout <<"魚群リーチ!!! 確変大当たり !スーパーラッキースタート"<<"当選回数"<<on++;min=count;}
     else if (*p == 400) { cout <<"魚群リーチ!!! 確変大当たり !スーパーラッキースタート"<<"当選回数"<<on++;min=count;}
     else if (*p == 500) { cout <<"魚群リーチ!!! 確変大当たり !スーパーラッキースタート"<<"当選回数"<<on++;min=count;}
     else if (*p == 600)  { cout <<"魚群リーチ!!! 大当たり !ラッキースタート"<<"当選回数"<<off++;min=count;}
     else if (*p == 700)  { cout <<"魚群リーチ!!! 大当たり !ラッキースタート"<<"当選回数"<<off++;min=count;}
     else if (*p == 785)  { cout <<"魚群リーチ!!! 大当たり !ラッキースタート"<<"当選回数"<<off++;min=count;}
     else if (*p == 816) { cout <<"魚群リーチ!!! 4R 確変!スーパーラッキースタート"<<"当選回数"<<on++;min=count;}
     else if (*p == 800) { cout <<"魚群リーチ!!! 15R 確変大当たり! 15Rスーパーラッキースタート15R"<<"当選回数"<<on++;min=count;}
     else if (*p == 900) { cout <<"魚群リーチ!!! 15R 確変大当たり! 15Rスーパーラッキースタート15R"<<"当選回数"<<on++;min=count;}
     else if (*p == 1001) { cout <<"魚群リーチ!!! 確変大当たり !スーパーラッキースタート"<<"当選回数"<<on++;min=count;}
     else if (*p == 1100) { cout <<"魚群リーチ!!! 確変大当たり !スーパーラッキースタート"<<"当選回数"<<on++;min=count;}
     else if (*p == 1200) { cout <<"魚群リーチ!!! 確変大当たり !スーパーラッキースタート"<<"当選回数"<<on++;min=count;}
     else if (*p == 1300) { cout <<"魚群リーチ!!! 確変大当たり !スーパーラッキースタート"<<"当選回数"<<on++;min=count;}
     else if (*p == 1400) { cout <<"魚群リーチ!!! 確変大当たり !スーパーラッキースタート"<<"当選回数"<<on++;min=count;}
     else if (*p == 1500) { cout <<"魚群リーチ!!! 大当たり !ラッキースタート"<<"当選回数"<<on++;min=count;}
     else if (*p == 1600) { cout <<"魚群リーチ!!! 大当たり !ラッキースタート"<<"当選回数"<<on++;min=count;}
     else if (*p == 1700) { cout <<"魚群リーチ!!! 8R 確変!スーパーラッキースタート"<<"当選回数"<<on++;min=count;}
     cout << endl;
     --i;
     }


     cin >> b;
      count++;


     if(a=!0){ goto start;}
     return 0;

    } 

     

     

     

     

     

    RND()は、乱数精度が一様ではなく悪いみたいなのでメルセンヌツイスタを使用する方が良いようです。

    この乱数だと65636個の中650個で100分の1にする事ができました。

    非常に実機に近いような動作になっていると思います。

    ネットで調べたところ 素人に分かりやすいような この関数についての詳しい使用法が無いようなので

    ご参考までにここに載せておきます。 詳しくは作者のページをご覧ください。

    ご参考になりましたらぜひ投票願います。

     

     

    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <iostream>

    #include <ctime>
    #include <random>
    #include <windows.h>
    #pragma comment(lib, "winmm.lib")

    using namespace std;


    /* Period parameters */ 
    #define N 624
    #define M 397
    #define MATRIX_A 0x9908b0dfUL   /* constant vector a */
    #define UPPER_MASK 0x80000000UL /* most significant w-r bits */
    #define LOWER_MASK 0x7fffffffUL /* least significant r bits */

    static unsigned long mt[N]; /* the array for the state vector  */
    static int mti=N+1; /* mti==N+1 means mt[N] is not initialized */

    /* initializes mt[N] with a seed */
    void init_genrand(unsigned long s)
    {
        mt[0]= s & 0xffffffffUL;
        for (mti=1; mti<N; mti++) {
            mt[mti] =
         (1812433253UL * (mt[mti-1] ^ (mt[mti-1] >> 30)) + mti);
            /* See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. */
            /* In the previous versions, MSBs of the seed affect   */
            /* only MSBs of the array mt[].                        */
            /* 2002/01/09 modified by Makoto Matsumoto             */
            mt[mti] &= 0xffffffffUL;
            /* for >32 bit machines */
        }
    }

    /* initialize by an array with array-length */
    /* init_key is the array for initializing keys */
    /* key_length is its length */
    /* slight change for C++, 2004/2/26 */
    void init_by_array(unsigned long init_key[], int key_length)
    {
        int i, j, k;
        init_genrand(19650218UL);
        i=1; j=0;
        k = (N>key_length ? N : key_length);
        for (; k; k--) {
            mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 30)) * 1664525UL))
              + init_key[j] + j; /* non linear */
            mt[i] &= 0xffffffffUL; /* for WORDSIZE > 32 machines */
            i++; j++;
            if (i>=N) { mt[0] = mt[N-1]; i=1; }
            if (j>=key_length) j=0;
        }
        for (k=N-1; k; k--) {
            mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 30)) * 1566083941UL))
              - i; /* non linear */
            mt[i] &= 0xffffffffUL; /* for WORDSIZE > 32 machines */
            i++;
            if (i>=N) { mt[0] = mt[N-1]; i=1; }
        }

        mt[0] = 0x80000000UL; /* MSB is 1; assuring non-zero initial array */
    }

    /* generates a random number on [0,0xffffffff]-interval */
    unsigned long genrand_int32(void)
    {
        unsigned long y;
        static unsigned long mag01[2]={0x0UL, MATRIX_A};
        /* mag01[x] = x * MATRIX_A  for x=0,1 */

        if (mti >= N) { /* generate N words at one time */
            int kk;

            if (mti == N+1)   /* if init_genrand() has not been called, */
                init_genrand(5489UL); /* a default initial seed is used */

            for (kk=0;kk<N-M;kk++) {
                y = (mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK);
                mt[kk] = mt[kk+M] ^ (y >> 1) ^ mag01[y & 0x1UL];
            }
            for (;kk<N-1;kk++) {
                y = (mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK);
                mt[kk] = mt[kk+(M-N)] ^ (y >> 1) ^ mag01[y & 0x1UL];
            }
            y = (mt[N-1]&UPPER_MASK)|(mt[0]&LOWER_MASK);
            mt[N-1] = mt[M-1] ^ (y >> 1) ^ mag01[y & 0x1UL];

            mti = 0;
        }
     
        y = mt[mti++];

        /* Tempering */
        y ^= (y >> 11);
        y ^= (y << 7) & 0x9d2c5680UL;
        y ^= (y << 15) & 0xefc60000UL;
        y ^= (y >> 18);

        return y;
    }

    /* generates a random number on [0,0x7fffffff]-interval */
    long genrand_int31(void)
    {
        return (long)(genrand_int32()>>1);
    }

    /* generates a random number on [0,1]-real-interval */
    double genrand_real1(void)
    {
        return genrand_int32()*(1.0/4294967295.0);
        /* divided by 2^32-1 */
    }

    /* generates a random number on [0,1)-real-interval */
    double genrand_real2(void)
    {
        return genrand_int32()*(1.0/4294967296.0);
        /* divided by 2^32 */
    }

    /* generates a random number on (0,1)-real-interval */
    double genrand_real3(void)
    {
        return (((double)genrand_int32()) + 0.5)*(1.0/4294967296.0);
        /* divided by 2^32 */
    }

    /* generates a random number on [0,1) with 53-bit resolution*/
    double genrand_res53(void)
    {
        unsigned long a=genrand_int32()>>5, b=genrand_int32()>>6;
        return(a*67108864.0+b)*(1.0/9007199254740992.0);
    }
    /* These real versions are due to Isaku Wada, 2002/01/09 added */

    int main(void)
    {
     char s;
     char ss;
     int i;
     int a=100;
     int b=65536;
     int ct=0;
     int cn=0;
     int v=0;
     unsigned long *p;
     
     unsigned long ul;
    long l;
    double d;


    start:

       init_genrand((unsigned long)timeGetTime());
     for(i=0;i<1;i++){
     ul=1+genrand_int32()%b;

     
     
      cout <<ul<<""<<endl;ct++;

      if((1<=ul)&&(ul<=350)){
       cout <<"5R50回大当たり"<<endl;cn=ct;v++;}
      else if((350<=ul)&&(ul<=650)){
       cout <<"5R25回大当たり"<<endl;cn=ct;v++;}

      
     
     
     
      }
     cout <<endl;
     cout <<"回転数"<<ct<<endl;
     cout <<"前回当たり回転数"<<cn<<"大当たり回数"<<v<<endl;
     cin>> ss;

     if(s=!0){ goto start;}
    }

    改正 

    #include <cstdio>
     #include <cstdlib>
     #include <cstring>
     #include <iostream>

    #include <ctime>
     #include <random>
     #include <windows.h>
     #pragma comment(lib, "winmm.lib")

    using namespace std;


     /* Period parameters */ 
     #define N 624
     #define M 397
     #define MATRIX_A 0x9908b0dfUL   /* constant vector a */
     #define UPPER_MASK 0x80000000UL /* most significant w-r bits */
     #define LOWER_MASK 0x7fffffffUL /* least significant r bits */

    static unsigned long mt[N]; /* the array for the state vector  */
     static int mti=N+1; /* mti==N+1 means mt[N] is not initialized */

    /* initializes mt[N] with a seed */
     void init_genrand(unsigned long s)
     {
         mt[0]= s & 0xffffffffUL;
         for (mti=1; mti<N; mti++) {
             mt[mti] =
          (1812433253UL * (mt[mti-1] ^ (mt[mti-1] >> 30)) + mti);
             /* See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. */
             /* In the previous versions, MSBs of the seed affect   */
             /* only MSBs of the array mt[].                        */
             /* 2002/01/09 modified by Makoto Matsumoto             */
             mt[mti] &= 0xffffffffUL;
             /* for >32 bit machines */
         }
     }

    /* initialize by an array with array-length */
     /* init_key is the array for initializing keys */
     /* key_length is its length */
     /* slight change for C++, 2004/2/26 */
     void init_by_array(unsigned long init_key[], int key_length)
     {
         int i, j, k;
         init_genrand(19650218UL);
         i=1; j=0;
         k = (N>key_length ? N : key_length);
         for (; k; k--) {
             mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 30)) * 1664525UL))
               + init_key[j] + j; /* non linear */
             mt[i] &= 0xffffffffUL; /* for WORDSIZE > 32 machines */
             i++; j++;
             if (i>=N) { mt[0] = mt[N-1]; i=1; }
             if (j>=key_length) j=0;
         }
         for (k=N-1; k; k--) {
             mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 30)) * 1566083941UL))
               - i; /* non linear */
             mt[i] &= 0xffffffffUL; /* for WORDSIZE > 32 machines */
             i++;
             if (i>=N) { mt[0] = mt[N-1]; i=1; }
         }

        mt[0] = 0x80000000UL; /* MSB is 1; assuring non-zero initial array */
     }

    /* generates a random number on [0,0xffffffff]-interval */
     unsigned long genrand_int32(void)
     {
         unsigned long y;
         static unsigned long mag01[2]={0x0UL, MATRIX_A};
         /* mag01[x] = x * MATRIX_A  for x=0,1 */

        if (mti >= N) { /* generate N words at one time */
             int kk;

            if (mti == N+1)   /* if init_genrand() has not been called, */
                 init_genrand(5489UL); /* a default initial seed is used */

            for (kk=0;kk<N-M;kk++) {
                 y = (mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK);
                 mt[kk] = mt[kk+M] ^ (y >> 1) ^ mag01[y & 0x1UL];
             }
             for (;kk<N-1;kk++) {
                 y = (mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK);
                 mt[kk] = mt[kk+(M-N)] ^ (y >> 1) ^ mag01[y & 0x1UL];
             }
             y = (mt[N-1]&UPPER_MASK)|(mt[0]&LOWER_MASK);
             mt[N-1] = mt[M-1] ^ (y >> 1) ^ mag01[y & 0x1UL];

            mti = 0;
         }
      
         y = mt[mti++];

        /* Tempering */
         y ^= (y >> 11);
         y ^= (y << 7) & 0x9d2c5680UL;
         y ^= (y << 15) & 0xefc60000UL;
         y ^= (y >> 18);

        return y;
     }

    /* generates a random number on [0,0x7fffffff]-interval */
     long genrand_int31(void)
     {
         return (long)(genrand_int32()>>1);
     }

    /* generates a random number on [0,1]-real-interval */
     double genrand_real1(void)
     {
         return genrand_int32()*(1.0/4294967295.0);
         /* divided by 2^32-1 */
     }

    /* generates a random number on [0,1)-real-interval */
     double genrand_real2(void)
     {
         return genrand_int32()*(1.0/4294967296.0);
         /* divided by 2^32 */
     }

    /* generates a random number on (0,1)-real-interval */
     double genrand_real3(void)
     {
         return (((double)genrand_int32()) + 0.5)*(1.0/4294967296.0);
         /* divided by 2^32 */
     }

    /* generates a random number on [0,1) with 53-bit resolution*/
     double genrand_res53(void)
     {
         unsigned long a=genrand_int32()>>5, b=genrand_int32()>>6;
         return(a*67108864.0+b)*(1.0/9007199254740992.0);
     }
     /* These real versions are due to Isaku Wada, 2002/01/09 added */

    int main(void)
     {
      char s;
      char ss;
      int i;
     
      const int b=65536;
      const int at=100;
      int ct=0;
      int cn=0;
      int nm=0;
      int v=0;
      int *va=0;
       int cunt[100];
       int count=0;
       int counte=0;

       int aa=0;
       int bb=0;
       int cc=0;
       int dd=0;
       int ee=0;
       int ff=0;
       int gg=0;
       int hh=0;
       int ii=0;
       int jj=0;
       int kk=0;
       int ll=0;
       int mm=0;
       int vc=0;
     
     
      unsigned long *p;
     
      unsigned long ul;
     long l;
     double d;
    //start:

     

     

       init_genrand((unsigned long)timeGetTime());
      for(i=0;i<500;i++){
      ul=1+genrand_int32()%b;
      ct++;

     
       if((1<=ul)&&(ul<=350)){vc++; nm++; count=vc;
      if (count==1){aa=i;} if(count==2){bb=i;}
       if(count==3){cc=i;} if(count==4){dd=i;}  if(count==5){ee=i;} if(count==6){ff=i;} if(counte==7){mm=i;}
       cout <<"5R50回大当たり"<<endl;
      
       }

     
     
       if((350<=ul)&&(ul<=650)){v++; cn++; counte=v;
      if (counte==1){gg=i;};if(counte==2){hh=i;};
       if(counte==3){ii=i;}  if(counte==4){jj=i;} if(counte==5){kk=i;}  if(counte==6){ll=i;}
        cout <<"5R25回大当たり"<<endl;
     
      
       }
    cout <<ul<<""<<endl;
     
     
      }
     
      
      cout <<endl;
       cout <<"総回転数"<<ct<<endl;

      cout <<"50回時短回数"<<nm<<endl;
      cout <<"25回時短回数"<<cn<<endl;
      cout <<"合計回数"<<nm+cn<<endl;
      cout <<"時短50 当たり回転数"<<aa<<"-1回" <<endl; 
      cout <<bb<<"-2回" <<cc<<"-3回" <<dd <<"-4回"<<ee<<"-5回" <<ff<<"-6回" <<mm <<"-7回"<<endl;
     
      cout <<"時短25 当たり回転数"<<gg<<"-1回" << hh <<"-2回"<<ii<<"-3回" <<jj <<"-4回"<<kk<<"-5回" <<ll<<"-6回" <<endl;
     
      cin >> s;

      //if(s=!0){ goto start;}
     
     }



    2013年6月9日 15:59
  • RND()は、乱数精度が一様ではなく悪いみたいなのでメルセンヌツイスタを使用する方が良いようです。

    書こうと思って忘れてました。rand()はかなり古いコードとの互換のために精度が低いものになっています。ただしVisual C++ 2008 SP1よりメルセンヌツイスタの乱数エンジンが提供されているので独自に実装する必要はありません。

    また乱数の使い方として %b とするのは安全ではありません。rand()の精度が悪く感じられるのもそのためです。一様分布を求めるのであれば、uniform_int_distributionクラスを使います。極端な一様乱数ジェネレーターを作るでこのクラスの使い方を見かけました。

    2013年7月10日 15:09
  • 外池と申します。

    シード値の与え方を適切にする、に尽きると思います。

    Azuleanさん、佐祐理さんが指摘されているシード値の与え方(srand())に留意・対応されれば、rand()で十分なはずです。提供されている関数の使い方をよく調べて理解した上で、適切な使い方をすることが肝要です。どんなに精度が高くてもシード値を必要とする関数の場合、シード値が同じだと毎回同じ乱数列になってしまいます。

    メルセンヌツイスタなんて、近所のコンビニまでの買い物にフェラーリに乗るようなもの。サンダルで、あるいはせいぜい自転車でいいじゃないですか。適材適所の関数を選んで、正しい使い方をすることです。サンダルだって、左右逆に履いたら、まともに歩けません。

    • 編集済み 外池 2013年7月11日 1:44 論点の明確化
    2013年7月11日 0:37
  • MSDN srand より:

    乱数の始点を設定します。


    Wikipadia の rand より:

    srandは乱数を初期化するものであるから、randを使用する度にsrandを呼んだりするのは、誤った用法である。


    Jitta@<a href="http://www.wankuma.com">わんくま同盟</a>

    2013年7月13日 4:31