2016-05-18 14 views
1

私は比較的新しいFortranで、RANDOM_NUMBERRANDOM_SEEDのサブルーチンを理解しようとしています。次のコードは、プログラムの先頭にあるDO LOOPの外側にジェネレータをシードするにもかかわらず、同じ乱数シーケンスを連続的に生成します。私は、コード乱数ジェネレータは、シードされていても同じシーケンスを生成します

Random number   1 =   0 
Random number   2 =   1 
Random number   3 =   2 
Random number   4 =   2 
Random number   5 =   1 
Random number   6 =   2 
Random number   7 =   0 
Random number   8 =   0 
Random number   9 =   3 
Random number   10 =   3 

私はこの正確な配列私は、コードを実行するたびに取得を実行したときにここで

1 PROGRAM TEST 
    2 
    3   IMPLICIT NONE 
    4   
    5   INTEGER :: I, OUTPUT 
    6   REAL :: R 
    7 
    8   CALL RANDOM_SEED() 
    9 
10   DO I=1, 10 
11     CALL RANDOM_NUMBER(R) 
12     OUTPUT = I*R 
13     PRINT *,'Random number ', I, ' = ', OUTPUT 
14   END DO 
15 
16 END PROGRAM TEST 

が出力されます。私はコンパイル時に再生成されるかどうかを確認するために再コンパイルを試みました。

+0

は、迅速なGoogle検索のリターンを行う:RANDOM_SEEDは、引数なしで呼び出された場合は、デフォルトの状態に初期化されます。パラメータに何も入力していない場合は、毎回同じ乱数列が返されるようです。 – DragonYen

+0

私はそのポストも見たことがありますが、引数を指定しないでrandom_seedを呼び出すと、デフォルトでシードとして使用する日付/時刻がフェッチされることになります(例えば、インテルフォーラムなど)。これについての私の解釈は、引数なしでRANDOM_SEEDを呼び出すと、コンピュータは自動的にシードされます。 –

+0

@ castled-rook、それはコンピュータに依存すると思います – Jodrell

答えて

1

私は専門家ではないが、some documentationを見ると、RANDOM_SEEDに番号を付ける必要があると思います。それ以外の場合は、乱数ジェネレータをデフォルト状態に初期化します。

"デフォルト状態"は実装に依存し、一部のプラットフォームでは固定値になります。あなたはこのような何かを行う必要があり、移植可能なコードを記述する必要がある場合は

subroutine init_random_seed() 
    use iso_fortran_env, only: int64 
    implicit none 
    integer, allocatable :: seed(:) 
    integer :: i, n, un, istat, dt(8), pid 
    integer(int64) :: t 

    call random_seed(size = n) 
    allocate(seed(n)) 
    ! First try if the OS provides a random number generator 
    open(newunit=un, file="/dev/urandom", access="stream", & 
     form="unformatted", action="read", status="old", iostat=istat) 
    if (istat == 0) then 
     read(un) seed 
     close(un) 
    else 
     ! Fallback to XOR:ing the current time and pid. The PID is 
     ! useful in case one launches multiple instances of the same 
     ! program in parallel. 
     call system_clock(t) 
     if (t == 0) then 
      call date_and_time(values=dt) 
      t = (dt(1) - 1970) * 365_int64 * 24 * 60 * 60 * 1000 & 
       + dt(2) * 31_int64 * 24 * 60 * 60 * 1000 & 
       + dt(3) * 24_int64 * 60 * 60 * 1000 & 
       + dt(5) * 60 * 60 * 1000 & 
       + dt(6) * 60 * 1000 + dt(7) * 1000 & 
       + dt(8) 
     end if 
     pid = getpid() 
     t = ieor(t, int(pid, kind(t))) 
     do i = 1, n 
      seed(i) = lcg(t) 
     end do 
    end if 
    call random_seed(put=seed) 
    contains 
    ! This simple PRNG might not be good enough for real work, but is 
    ! sufficient for seeding a better PRNG. 
    function lcg(s) 
     integer :: lcg 
     integer(int64) :: s 
     if (s == 0) then 
     s = 104729 
     else 
     s = mod(s, 4294967296_int64) 
     end if 
     s = mod(s * 279470273_int64, 4294967291_int64) 
     lcg = int(mod(s, int(huge(0), int64)), kind(0)) 
    end function lcg 
    end subroutine init_random_seed 
関連する問題