Oke sekarang untuk menambah jawaban dengan @ Jerry101, saya telah menulis kode yang dimodifikasi. Di sini, masalah utamanya adalah IMAXINV
tidak secara eksplisit dideklarasikan sebagai REAL
, sehingga ditafsirkan sebagai INTEGER
(akibatnya, IMAXINV = 1.0 / IMAX
selalu menjadi 0 pada kode aslinya). Juga, saya telah menghapus ISEED
dari blok COMMON
(karena diteruskan sebagai argumen) dan memasukkan pernyataan COMMON
lainnya ke dalam RANDU
untuk berbagi variabel di antara rutinitas. Dengan modifikasi ini program tampaknya bekerja dengan benar.
PROGRAM RANDOM
COMMON RANDOMNUMBER !<--- ISEED is deleted from here
ISEED = 123
J=1
7 CALL RANDU(ISEED)
J=J+1
WRITE(*,*) RANDOMNUMBER !<--- write to STDOUT for test
IF (J < 100) GOTO 7
END
SUBROUTINE RANDU(ISEED)
real IMAXINV !<--- this is necessary
COMMON RANDOMNUMBER !<--- this is also necessary to share variables
PARAMETER (IMAX = 2147483647, IMAXINV = 1./IMAX)
ISEED = ISEED * 65539
IF(ISEED<0) ISEED = ISEED + IMAX + 1
RANDOMNUMBER = ISEED * IMAXINV
END
Seperti yang disarankan dalam Jawaban lain, kita juga bisa menggunakan FUNCTION
untuk mengembalikan variabel secara langsung. Maka kita tidak perlu menggunakan COMMON
, sehingga kodenya menjadi sedikit lebih bersih.
PROGRAM RANDOM
ISEED = 123
J=1
7 RANDOMNUMBER = RANDU(ISEED)
J=J+1
WRITE(*,*) RANDOMNUMBER
IF (J < 100) GOTO 7
END
FUNCTION RANDU(ISEED)
real IMAXINV
PARAMETER (IMAX = 2147483647, IMAXINV = 1./IMAX)
ISEED = ISEED * 65539
IF(ISEED<0) ISEED = ISEED + IMAX + 1
RANDU = ISEED * IMAXINV !<--- "RANDU" is the return variable
END
Namun perhatikan bahwa ketika FUNCTION
digunakan, tipe variabel kembalian harus dideklarasikan secara eksplisit dalam rutinitas pemanggilan jika nama fungsi tidak sesuai dengan aturan implisit. (Pada kode di atas, RANDU
tidak dideklarasikan secara eksplisit karena diartikan sebagai REAL
). Jadi, ada banyak peringatan dalam aturan pengetikan implisit di Fortran77...
Catatan tambahan:
Untuk menghindari kesalahan ini, saya sarankan menggunakan Fortran >=90 (daripada Fortran77) karena Fortran menyediakan banyak fitur untuk mencegah kesalahan tersebut. Misalnya, kode yang dimodifikasi secara minimal mungkin terlihat seperti ini:
module mymodule
contains
subroutine randu ( istate, ran )
implicit none
integer, parameter :: IMAX = 2147483647
real, parameter :: IMAXINV = 1.0 / IMAX
integer, intent(inout) :: istate
real, intent(out) :: ran
istate = istate * 65539
if ( istate < 0 ) istate = istate + IMAX + 1
ran = istate * IMAXINV
end subroutine
end module
program main
use mymodule, only: randu
implicit none
integer :: j, istate
real :: randomnumber
istate = 123 !! seed for RANDU()
do j = 1, 99
call randu ( istate, randomnumber )
write(*,*) randomnumber
enddo
end program
Di Sini,
implicit none
digunakan untuk menegakkan deklarasi semua variabel secara eksplisit. Hal ini berguna untuk membantu menghindari kesalahan pengetikan variabel (seperti IMAXINV
pada Pertanyaan!).
- Subrutin
RANDU
terkandung dalam module
sehingga kompiler menyediakan antarmuka eksplisit dan banyak pemeriksaan berguna (singkatnya, module
adalah sesuatu seperti namespace di C++). module
juga dapat digunakan untuk mendefinisikan variabel global dengan cara yang jauh lebih aman daripada COMMON
.
- Saya menggunakan konstruksi
do
... enddo
untuk mengulang j
daripada menambahnya secara manual dan menggunakan goto
. Yang pertama sebenarnya lebih mudah digunakan, dan juga goto
cenderung membuat kode sering kali kurang mudah dibaca...
- Saya menamai file program tersebut sebagai "test.f90" (perhatikan akhiran .f90), yang memungkinkan format bebas. Selain itu, boleh saja menggunakan huruf kecil untuk variabel.
- [Juga, karena
iseed
menyimpan informasi tentang status terkini dari pembuat nomor acak (semu), mungkin lebih baik menggunakan beberapa nama variabel yang berbeda (seperti isstate dll?) untuk mengingatkan bahwa nilainya perlu disimpan selama panggilan.]
Jadi jika Anda tertarik, harap pertimbangkan untuk menggunakan versi Fortran yang lebih modern (daripada Fortran77) yang memungkinkan kami menulis kode yang lebih aman dan kuat :)
person
roygvib
schedule
18.10.2015