FORTRAN
Real Werte und Vergleiche
Ein wichtiger Punkt bei der Programmierung mit Fortran ist die Behandlung der Real Werte. Insbesondere der vergleich, ob zwei Real Werte gleich sind, ist in FORTRAN nur durch eine erweiterte Syntax möglich.
Zuweisen von Werten
real*4 a real*8 b a = 0.123e0 !das e0 kennzeichnet den Wert als real*4 b = 0.123d0 !das d0 kennzeichnet den Wert als real*8
Vergleich von Realzahlen
- siehe Bug 367
Früher wurde im Rechenkern mit unterschiedlichen Vergleichen gerechnet (GLOBAL_NULL
, GLOBAL_FASTNULL
etc.)
Momentan verwendet:
R8_EPSILON = 2 * Epsilon(1.2345d0) R4_EPSILON = 2 * Epsilon(1.2654E0) ! entspricht 2**-23
Diskussion:
real*4 a real*4 b logical isNull isNull = (a == b) !wird so gut wie nie erfüllt isNull = (ABS(a - b) < 1E-15) !früher im Projekt verwendet (GLOBAL_NULL) !Alternativen (zur Diskussion) isNull = (ABS(a - b) < Epsilon(a)) !nach Rechenoperationen erwies sich Epsilon als zu ungenau bzw. genau isNull = (ABS(a / b - 1.0E0) < eps) !Relativvergleich - führte bei Tests aber zu Fehlern isNull = (ABS(a - b) < SPACING(0.0E0))
Anmerkung
Im Code von BlueM sind ein paar nicht korrekte Anweisungen enthalten:
! FALSCH MAX(dumdidum, R8_EPSILON) MAX(dumdidum, R4_EPSILON)
Korrekt ist aber:
! RICHTIG MAX(dumdidum, 0.0D0) MAX(dumdidum, 0.0E0)
Links
- Vergleich von Realwerten
- Aus dem Intel-Forum
- Guter Artikel über Problematik: The Perils of Floating Point
Übergabe von Arrays
In Fortran ist es möglich Teile von Arrays an Funktionen zu übergeben.
Dabei wird der Subroutine (oder function) einfach der "Anfangswert" übergeben - z.B. func_array(Huba(1,2,1))
.Von diesem Startpunkt wird, dann in der Subroutine ein entsprechendes Array gebildet. Erwartet beispielsweise die Subroutine einen Vektor, dann werden vom jenem Startpunkt an alle Werte der ersten Dimension übernommen. Analog verhält es sich bei mehrdimiensionalen Arrays.
- Anmerkung
- Das Array der Subroutine sollte natürlich kleiner sein, als das Übergebene (vom Startpunkt gezählt) !
Das Beispiel verdeutlicht dies:
!--------------------------------------------------------------- subroutine TestArrayFortranFortran() integer arr(3,4) integer i integer j do i = 1, ubound(arr,1) do j = 1, ubound(arr,2) arr(i,j) = i + (j-1)*3 write(*,'("Matrix (", I4,",",I4,") = ",I4)') i,j,arr(i,j) end do end do write(*,'("Aufruf mit arr(1,1) ")') call TestArrayFortranFortran_SUB(arr(1,1)) write(*,'("Aufruf mit arr(2,1) ")') call TestArrayFortranFortran_SUB(arr(2,1)) write(*,'("Aufruf mit arr(1,2) ")') call TestArrayFortranFortran_SUB(arr(1,2)) write(*,'("Aufruf mit arr(2,2) ")') call TestArrayFortranFortran_SUB(arr(2,2)) end subroutine !--------------------------------------------------------------- !--------------------------------------------------------------- subroutine TestArrayFortranFortran_SUB(arr) integer arr(2) integer i do i = 1, ubound(arr,1) write(*,'("Vektor ", I4)') arr(i) end do end subroutine !---------------------------------------------------------------
Fixed Form und Free Form
Die Free Form ist der Fixed Form der übersichtlichkeitshalber vorzuziehen. Ausserdem können bei der Fixed Form Fehler entstehen, die der compiler nicht abfängt (z. B. Formeln die über den Rand gehen - in SMUSI war beispielsweise eine Stelle, wo statt mit 300 nur mit 3 multipliziert wurde.
Für die Umstellung gibts hier eine regular Expression, die alle Zeilen anzeigt die länger als 72 Zeichen sind:
Identifizieren von Problemstellen
^[^cC!][^!]^72
Visualisierung unter [1]
Bereinigen von Leerzeichen am Ende
(:b+)$
Visualisierung unter [2]