2

ランダムなエルミート行列エルミート行列を生成する小さなコードです。

rand() を呼び出すたびに srand() を呼び出しました。しかし、出力にはまだランダム性がありません。

c99 の複雑なデータ型機能を使用して、エルミート行列を作成しました。どこが間違っているのかわかりません:(

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

#define MATSIZE 5
#define RAND_RANGE 100

double complex mat[MATSIZE][MATSIZE];

void gen_mat()
{
  int i =0,j;
  int real;
  int img;
  for( ;i < MATSIZE; i++)
  {
    srand(time(NULL));
    real = rand()%RAND_RANGE + 1;
    srand(time(NULL));
    img = rand()%RAND_RANGE + 1;
    for(j = MATSIZE; j != i ; j--) 
    { 
       mat[i][j] = real + img * I;
       mat[j][i] = conj(mat[i][j]);
    }
    srand(time(NULL));
    if(i == j)
      mat[i][i] = rand()%RAND_RANGE + 0*I;
  }
}

void print_mat()
{
  int i,j;
  for(i = 0; i < MATSIZE; i++)
  {
    for(j = 0; j < MATSIZE; j++)
    {
      printf("%f + %f *i", creal(mat[i][j]), cimag(mat[i][j]));
      printf("    ");
    }
    puts("\n");
  }
}

int main()
{
  gen_mat();
  print_mat();
  return 0;
}

サンプル出力

[aft@centos-c physics-numaric]$ ./a.out 
66.000000 + 0.000000 *i    67.000000 + 67.000000 *i    67.000000 + 67.000000 *i             67.000000 + 67.000000 *i    67.000000 + 67.000000 *i    

67.000000 + -67.000000 *i    66.000000 + 0.000000 *i    67.000000 + 67.000000 *i      67.000000 + 67.000000 *i    67.000000 + 67.000000 *i    

67.000000 + 67.000000 *i    67.000000 + -67.000000 *i    66.000000 + 0.000000 *i    67.000000 + 67.000000 *i    67.000000 + 67.000000 *i    

67.000000 + 67.000000 *i    67.000000 + -67.000000 *i    67.000000 + -67.000000 *i    66.000000 + 0.000000 *i    67.000000 + 67.000000 *i    

67.000000 + 67.000000 *i    67.000000 + -67.000000 *i    67.000000 + -67.000000 *i      67.000000 + -67.000000 *i    66.000000 + 0.000000 *i    

main() で srand を呼び出す EDIT は、実際に問題を解決しました。君たちありがとう。

[aft@centos-c physics-numaric]$ ./a.out 
31.000000 + 0.000000 *i    81.000000 + 75.000000 *i    81.000000 + 75.000000 *i     81.000000 + 75.000000 *i    81.000000 + 75.000000 *i    

81.000000 + -75.000000 *i    53.000000 + 0.000000 *i    69.000000 + 57.000000 *i    69.000000 + 57.000000 *i    69.000000 + 57.000000 *i    

69.000000 + 57.000000 *i    69.000000 + -57.000000 *i    27.000000 + 0.000000 *i    93.000000 + 11.000000 *i    93.000000 + 11.000000 *i    

93.000000 + 11.000000 *i    69.000000 + -57.000000 *i    93.000000 + -11.000000 *i    58.000000 + 0.000000 *i    76.000000 + 78.000000 *i    

76.000000 + 78.000000 *i    69.000000 + -57.000000 *i    93.000000 + -11.000000 *i    76.000000 + -78.000000 *i    67.000000 + 0.000000 *i    
4

4 に答える 4

8

srandへのすべての呼び出しの前に呼び出さないでくださいrand。プログラムの開始時に一度呼び出します。

于 2012-04-21T12:48:14.690 に答える
6

srandループの場合は内部で呼び出さないでください。一度だけ呼び出します。

srand(time(NULL));
for( ;i < MATSIZE; i++)
{
    // ... calls to rand()   
}

それ以外の場合は、ランダム ジェネレーターに同じシードをシードします (同じ時間を取得するのに十分な速さがあるため)。

ところで、多くの場合、ランダム生成を含む多くのものを初期化するプログラム/シーケンスの init 関数を作成するのは非常に慣習的です (例: call srand())

于 2012-04-21T12:48:19.257 に答える
1

これを行わないでください:

rand()%RAND_RANGE + 0*I;

、RAND_RANGEとRAND_MAX + 1が分割されない場合、低い値がオーバーサンプリングされるためです。(これは「ほとんど常に」の場合です)

また、time_tの粒度は1秒であるため、time(NULL)に基づいてジェネレーターを再起動すると、ほとんどの場合、まったく同じ値で再起動します。

最終:rand_maxには、少なくとも15ビット(32K)相当のランダムが含まれます。古いシステムは、実際には32Kのサイクルで15ビットしか配信しない可能性があります。

更新:これはwakkerbotからのスニペットです。urnd()関数は、0と範囲の間のバイアスのない値を返そうとします。テストはおそらくもっとエレガントに実行できます。

typedef unsigned long long BigThing;

unsigned int urnd(unsigned int range)
{
    static bool flag = FALSE;

    if (flag == FALSE) {
#if defined(__mac_os) || defined(DOS)
        srand(time(NULL));
#else
        srand48(time(NULL));
#endif
    }
    flag = TRUE;
#if defined(__mac_os) || defined(DOS)
    return rand()%range;
#else

if (range <= 1) return 0;

while(1)        {
    BigThing val, box;
#if WANT_RDTSC_RANDOM
    val = rdtsc_rand();
#else
    val =  lrand48();
#endif
/* we need this to avoid oversampling of the lower values.
 * Oversampling the lower values becomes more of a problem if (UNSIGNED_MAX/range) gets smaller
 */
    box = val / range;
    if ((1+box) *range < range) continue;
    return val % range;
        }
#endif
}
于 2012-04-21T13:04:32.837 に答える
1

乱数ジェネレーターにsrand()毎回シードを設定する必要はありません。プログラムの最初に一度呼び出すだけです。rand()次に、次の乱数を取得するために呼び出します。

于 2012-04-21T12:48:47.883 に答える