Topik ini membahas empat tipe intrinsik Fortran, yaitu integer, real, logical, dan character, beserta konsep kind yang memilih presisi sebuah tipe. Konstanta bernama real32 dan real64 dari modul iso_fortran_env diperkenalkan sebagai cara memilih presisi secara portabel. Kehilangan presisi yang dialami tipe real default ditunjukkan dengan program yang dapat dijalankan, sehingga perbedaan hasil pada real32 dan real64 dapat diamati langsung dari keluarannya.
Empat tipe intrinsik#
Tipe intrinsik (intrinsic type) adalah tipe yang sudah disediakan bahasa tanpa perlu didefinisikan ulang. Keempatnya mencakup bilangan bulat (integer), bilangan pecahan (real), nilai kebenaran (logical), dan teks (character). Setiap variabel dideklarasikan dengan menuliskan nama tipe, tanda titik dua ganda ::, lalu daftar nama variabel, dan setiap variabel baru diberi nilai lewat penugasan sebelum digunakan.
program tipe
use, intrinsic :: iso_fortran_env, only : real32, real64
implicit none
integer :: jumlah
real :: suhu
logical :: valid
character(len=12) :: nama
real(real32) :: x32
real(real64) :: x64
jumlah = 42
suhu = 30.5
valid = .true.
nama = "Fortran"
x32 = 1.0_real32
x64 = 1.0_real64
print *, "integer :", jumlah
print *, "real :", suhu
print *, "logical :", valid
print *, "character : " // trim(nama)
print *, "kind integer default:", kind(jumlah)
print *, "kind real default :", kind(suhu)
print *, "kind real32 :", kind(x32)
print *, "kind real64 :", kind(x64)
end program tipe# kompilasi program tipe menjadi berkas executable bernama tipe
gfortran tipe.f90 -o tipe
# jalankan program hasil kompilasi
./tipe integer : 42
real : 30.5000000
logical : T
character : Fortran
kind integer default: 4
kind real default : 4
kind real32 : 4
kind real64 : 8Program di atas mendeklarasikan satu variabel untuk setiap tipe intrinsik, ditambah dua variabel real berkind berbeda yang dibahas pada bagian berikutnya. Pada keluaran, nilai logical ditulis T untuk true dan F untuk false, sedangkan nilai real ditampilkan dengan sekitar tujuh digit di bagian desimal. Deklarasi character(len=12) menetapkan panjang teks 12 karakter, dan nilai yang lebih pendek dilengkapi spasi di belakangnya hingga penuh. Oleh karena itu, intrinsik trim dipanggil untuk membuang spasi kosong di akhir teks, sedangkan operator // menggabungkan dua nilai character sebelum dicetak. Penugasan teks yang lebih panjang daripada deklarasi justru memotong sisa karakternya, sehingga panjang len perlu dipilih dengan menyisakan ruang cadangan yang cukup.
Konsep kind dan konstanta presisi#
Setiap tipe intrinsik memiliki satu atau lebih kind, yaitu parameter yang memilih salah satu dari beberapa representasi internal untuk tipe tersebut. Dua variabel real berkind berbeda dapat berbeda presisi dan rentang walaupun tipenya sama. Intrinsik kind() melaporkan nilai kind sebuah variabel, dan keluaran program di atas menunjukkan kind(jumlah) bernilai 4, sedangkan kind(x64) bernilai 8.
Angka 4 dan 8 tersebut adalah pilihan gfortran, bukan jaminan standar. Standar hanya menentukan bahwa kind yang lebih besar menampung rentang dan presisi yang lebih baik, sedangkan angkanya sendiri bergantung compiler. Deklarasi dengan angka kind langsung seperti real(kind=8) karenanya rapuh ketika berpindah compiler.
Modul intrinsik iso_fortran_env menyediakan konstanta bernama yang menyatakan presisi dalam jumlah bit, sehingga pilihan menjadi portabel. Perintah use di baris kedua program di atas memuat real32 untuk presisi tunggal (single precision) dan real64 untuk presisi ganda (double precision). Modul yang sama juga memuat int32 dan int64 untuk memilih presisi integer, dengan penulisan yang sama persis. Tipe character dan logical juga menerima kind, tetapi kind default sudah cukup dalam praktik, dan pilihan presisi yang penting berada pada real serta integer.
! tidak-dijalankan
use, intrinsic :: iso_fortran_env, only : real32, real64
real(real64) :: pi
pi = 3.141592653589793_real64Deklarasi real(real64) memilih representasi 64 bit, sedangkan sufiks _real64 pada literal memberi tahu compiler bahwa konstanta tersebut harus disimpan dengan kind yang sama. Apabila sufiks dihilangkan, literal dibulatkan ke real default terlebih dahulu, sehingga digit ekstra tidak pernah tersimpan. Sufiks kind seperti _real32 dan _real64 karenanya dituliskan pada setiap literal yang menuntut presisi tertentu. Sebelum konstanta dari iso_fortran_env menjadi cara yang lazim, presisi dipilih dengan intrinsik selected_real_kind(p), dan bentuk tersebut masih sering ditemui pada kode lama.
Kehilangan presisi pada real default#
Real default pada gfortran setara real32, yaitu presisi tunggal dengan sekitar enam sampai tujuh digit signifikan. Presisi semacam itu cukup untuk banyak keperluan sehari-hari, tetapi menjadi masalah ketika perhitungan menumpuk banyak operasi. Penyebab dasarnya bukan bug, melainkan fakta bahwa sebagian bilangan desimal tidak pernah dapat disimpan persis dalam sistem biner. Bilangan yang pendek pada sistem desimal menjadi pecahan biner tak berhingga, sehingga hanya nilai terdekatnya yang tersimpan.
program presisi
use, intrinsic :: iso_fortran_env, only : real32, real64
implicit none
real(real32) :: a32, b32
real(real64) :: a64, b64
a32 = 0.1_real32
b32 = 0.2_real32
a64 = 0.1_real64
b64 = 0.2_real64
print *, "digit presisi real32 :", precision(a32)
print *, "digit presisi real64 :", precision(a64)
print *, "0.1 + 0.2 real32 :", a32 + b32
print *, "0.1 + 0.2 real64 :", a64 + b64
end program presisi# kompilasi program presisi menjadi berkas executable bernama presisi
gfortran presisi.f90 -o presisi
# jalankan program hasil kompilasi
./presisi digit presisi real32 : 6
digit presisi real64 : 15
0.1 + 0.2 real32 : 0.300000012
0.1 + 0.2 real64 : 0.30000000000000004Kedua baris terakhir menghitung penjumlahan yang sama pada dua kind. Pada real32, hasilnya 0.300000012, yang berarti selisih dari 0.3 yang seharusnya sudah terlihat pada digit kedelapan. Pada real64, selisih baru muncul pada digit ketujuh belas, yaitu 0.30000000000000004.
Intrinsik precision() melaporkan jumlah digit desimal yang dapat diandalkan, yaitu 6 untuk real32 dan 15 untuk real64 pada gfortran, sedangkan intrinsik huge() dan range() dari kelompok yang sama melaporkan nilai terbesar serta rentang eksponen sebuah kind. Keluaran semacam ini menjadi alasan mengapa perbandingan dua nilai real dengan operator == berisiko, karena dua nilai yang secara matematis sama dapat tersimpan berbeda pada digit terakhir. Perbedaan semacam ini terasa ketika penjumlahan berulang, karena selisih kecil pada setiap operasi ikut menumpuk seiring banyaknya langkah.
Ringkasan#
- Empat tipe intrinsik adalah
integer,real,logical, dancharacter, dengan deklarasi berbentuktipe :: nama. - Kind memilih representasi internal sebuah tipe, dan angkanya bergantung compiler, sehingga konstanta
real32danreal64dariiso_fortran_envlebih aman daripada angka kind langsung. - Literal diberi sufiks kind seperti
0.1_real64agar konstanta tersimpan pada kind yang diinginkan sejak awal. - Real default bertipe presisi tunggal dengan sekitar enam digit signifikan, sehingga
0.1 + 0.2tidak persis 0.3.
Referensi#
- Fortran Intrinsics — fortran-lang.org
— Rujukan intrinsik standar seperti
kind,precision, dantrimbeserta kelompok fungsinya. - ISO_FORTRAN_ENV — GNU Fortran manual
— Dokumentasi konstanta
REAL32,REAL64, dan konstanta lain pada modul intrinsik tersebut.