2016-05-18 8 views
1

Ich bin relativ neu in Fortran und versuche, die RANDOM_NUMBER und RANDOM_SEED Unterprogramme zu verstehen. Der folgende Code produziert fortwährend die gleiche Folge von Zufallszahlen, obwohl ich den Generator außerhalb des DO LOOP am Anfang des Programms setze. HierZufallsgenerator erzeugt die gleiche Sequenz, obwohl es gesät ist

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 

ist der Ausgang, wenn ich den Code ausführen

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 

Ich erhalte diese genaue Reihenfolge jedes Mal, wenn ich den Code ausführen. Ich habe sogar versucht, neu zu kompilieren, um zu sehen, ob der Generator zur Kompilierzeit neu seed.

+0

eine schnelle Google-Suche kehrt tun: Wenn random_seed ohne Argumente aufgerufen wird, wird es zu einem Standardzustand initialisiert. Es scheint, dass Sie wahrscheinlich jedes Mal dieselbe Zufallszahlenfolge erhalten würden, wenn Sie in den Parametern nichts liefern. – DragonYen

+0

Ya Ich habe diesen Beitrag auch gesehen, aber ich habe dann weiter gelesen (zum Beispiel in einem Intel-Forum), dass wenn Sie random_seed ohne Argument aufrufen, der Computer das Datum/die Zeit abrufen wird, um sie standardmäßig zu verwenden. Meine Interpretation von diesem war, dass, wenn Anruf RANDOM_SEED ohne Argument der Computer automatisch –

+0

@ rowed-rook, ich denke, es hängt von dem Computer – Jodrell

Antwort

1

Ich bin kein Experte, aber mit Blick auf some documentation, ich denke, Sie müssen RANDOM_SEED mit einer Nummer aufrufen, sonst initialisiert es den Zufallsgenerator in einen Standardzustand.

Der "Standardstatus" ist implementierungsabhängig und wird auf manchen Plattformen ein fester Wert sein.

Wenn Sie Sie portablen Code schreiben müssen etwas tun sollte,

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 
Verwandte Themen