2

私はこの機能を使用しています:

int rand2(int lim)
{
        static long a = 1;  // could be made the seed value
        a = (a * 32719 + 3) % 32749;
        return ((a % lim) + 1);
}

乱数のスタックを取得するには、正常に動作しますが、この関数を起動するたびに同じ番号のスタックがあるため、time() システム関数を使用して毎回異なるスタックを取得したいと考えています

int rand3(int lim, int dat_time)
{
  static int a = dat_time; // could be made the seed value                                                       
  a = (a * 32719 + 3) % 32749;
  return ((a % lim) + 1);
}

次に、変数aが静的であるため、コンピューターのtime()を1回与えます

int             main()
{
  int           rd;
  time_t        timee;
  int           seed;

  timee = 0;
  timee = time(timee);
  seed = timee;
  while(42)
    {
      rd = rand3(52, seed);
      printf("%d\n", rd);
      getchar();
    }
}

次に、dat_time が定数ではないというエラーが表示されますが、一度使用するので理由がわかりません

4

4 に答える 4

3

静的ストレージ期間変数は、コードの実行が開始される前に初期化され、コンパイル時に計算可能な式で初期化する必要があります。

つまり、実行時まで決定できない変数を使用して初期化しないということです。を削除するstaticと、エラーは消えますが、呼び出すたびに乱数ジェネレーターを再シードすることになります。

最初の乱数を要求する前に ( C 標準ライブラリのように)乱数シードを一度srand()/rand()初期化してから、乱数関数を使用してシーケンス内の値を循環させる必要があります。それは次のようなもので行うことができます:

int rand4 (int numLimit) {
    static int randSeed, needsInit = 1;
    if (needsInit) {                      // This bit only done once.
        randSeed = time(0);
        needsInit = 0;
    }
    randSeed = (randSeed * 32719 + 3) % 32749;
    return (randSeed % numLimit) + 1;
}

典型的な実装srand()/rand()次のようになります。

// RAND_MAX assumed to be 32767.
static unsigned long int next = 1;
void srand(unsigned int seed) { next = seed; }
int rand(void) {
    next = next * 1103515245 + 12345;
    return (unsigned int)(next/65536) % 32768;
}

nextシードがビューから隠されるように、独自のソース ファイルで。rand()これは、最初に を呼び出さずに呼び出すsrand()と、 を呼び出した場合と同じであるという予想される動作に従いますsrand (1)


そして、1 から 52 までのすべての数字を生成するには特定の数の呼び出しが必要であるというコメントに基づいて、これを使用してランダム化されたカードのデッキを生成しているように思えます。その場合、乱数を生成して既に見たものを破棄するよりも良い方法があります。

そのソリューションは、残りのデッキのサイズがどんどん小さくなっていくにつれて急速に劣化します。O(1) 時間と空間の解の場合は、Fisher-Yates シャッフルを使用します。

基本的なアルゴリズムは、並べ替えられていないリストを使用し、最後の要素をランダムに選択された要素と単純に交換して、リストのサイズを 1 減らします。

dim n[N]                  // gives n[0] through n[N-1]

for each i in 0..N-1:     // initialise them to their indexes
    n[i] = i              // (use i+1 for 1-10 instead of 0-9).

nsize = N                 // starting pool size
do N times:
    i = rnd(nsize)        // give a number between 0 and nsize-1
    print n[i]
    nsize = nsize - 1     // these two lines effectively remove the used number
    n[i] = n[nsize]

それによって生成される数値は次のとおりです。

<------ n[] ------>
0 1 2 3 4 5 6 7 8 9  nsize  rnd(nsize)  output
-------------------  -----  ----------  ------
0 1 2 3 4 5 6 7 8 9     10           4       4
0 1 2 3 9 5 6 7 8        9           7       7
0 1 2 3 9 5 6 8          8           2       2
0 1 8 3 9 5 6            7           6       6
0 1 8 3 9 5              6           0       0
5 1 8 3 9                5           2       8
5 1 9 3                  4           1       1
5 3 9                    3           0       5
9 3                      2           1       3
9                        1           0       9
于 2013-10-02T08:58:17.100 に答える
0

シードを乱数ジェネレーター関数に渡す場合は、呼び出しごとにシードを変更するように注意する必要があります。そうしないと、常に同じ数値が得られます。

代わりに、標準srandrand関数で使用されるパターンを再利用して、シードを設定する関数と乱数を取得する関数の 2 つの関数を作成することをお勧めします。シードは、関数内の静的変数ではなくグローバル変数になります。


もちろん、単一の関数を使用することもできますが、関数はシードを変更できる必要がありますこれは、参照によって「シード」/「状態」引数を渡すことで実現できます。

int rand3(int lim, int *state)
{
    *state = (*state * 32719 + 3) % 32749;
    return ((*state % lim) + 1);
}

&次に、関数を呼び出すときにaddress-of 演算子を使用する必要があります。

int rng_state = time(NULL);  /* See the initial state (aka seeding) */

for (int i = 0; i < 10; ++i)
    printf("A random number: %d\n", rand3(52, &rng_state));
于 2013-10-02T08:59:39.510 に答える
0

int a = dat_time から static を削除し、乱数からの戻り値を次のシードとして使用します。

int rand3(int lim, int dat_time)
{
  int a = dat_time; // could be made the seed value                                                       
  a = (a * 32719 + 3) % 32749;
  return ((a % lim) + 1);
}

int             main()
{
  int           rd;
  time_t        timee;
  int           seed;

  timee = 0;
  timee = time(timee);
  seed = timee;
  while(42)
  {
      rd = rand3(52, seed);
      printf("%d\n", rd);
      getchar();
      seed = rd;   // < Use the new random number as the seed for the next one
  }
}
于 2013-10-02T08:58:04.740 に答える
-1

これはうまくいくはずです、私はそれを書きました::

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

int main ( void )
{
  int r;

  srand ( (unsigned)time ( NULL ) );
  r = rand();

  printf ( "random number = %d\n", r );

  return 0;
}

しかし、静的キーワードを削除することをお勧めします

static int a = dat_time; // could be made the seed value
于 2013-10-02T09:14:36.357 に答える