FORTRAN: Difference between revisions
(→Real Werte und Vergleiche: aktualisiert) |
|||
Line 35: | Line 35: | ||
'''Momentan verwendet:''' | '''Momentan verwendet:''' | ||
<fortran> | <fortran> | ||
R8_EPSILON = | R8_EPSILON = 2 * Epsilon(1.2345d0) | ||
R4_EPSILON = 2 * Epsilon(1.2654E0) ! entspricht 2**-23 | |||
</fortran> | </fortran> | ||
Line 44: | Line 45: | ||
logical isNull | logical isNull | ||
isNull = (a == b) !wird | 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) | !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)) | |||
isNull = ( | |||
</fortran> | </fortran> | ||
Line 60: | Line 58: | ||
Im Code von BlueM sind ein paar nicht korrekte Anweisungen enthalten: | Im Code von BlueM sind ein paar nicht korrekte Anweisungen enthalten: | ||
<fortran> | <fortran> | ||
MAX(dumdidum,R8_EPSILON) | MAX(dumdidum, R8_EPSILON) | ||
MAX(dumdidum,R4_EPSILON) | MAX(dumdidum, R4_EPSILON) | ||
</fortran> | </fortran> | ||
Korrekt ist aber: | Korrekt ist aber: | ||
<fortran> | <fortran> | ||
MAX(dumdidum,0.0D0) | MAX(dumdidum, 0.0D0) | ||
MAX(dumdidum,0.0E0) | MAX(dumdidum, 0.0E0) | ||
</fortran> | </fortran> | ||
Revision as of 06:24, 10 October 2008
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:
Identizieren von Problemstellen
^[^cC!][^!]^72
Bereinigen von Leerzeichen am Ende
(:b+)$
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 gelich sind, ist in FORTRAN nur durch eine erweiterte Syntax möglich.
Zuweisen von Werten:
<fortran> 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 </fortran>
Vergleich von Realzahlen
- siehe Bug 367
Früher wurde im Rechenkern mit unterschiedlichen Vergleichen gerechnet (GLOBAL_NULL
, GLOBAL_FASTNULL
etc.)
Momentan verwendet: <fortran> R8_EPSILON = 2 * Epsilon(1.2345d0) R4_EPSILON = 2 * Epsilon(1.2654E0) ! entspricht 2**-23 </fortran>
Diskussion: <fortran> 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)) </fortran>
Anmerkung
Im Code von BlueM sind ein paar nicht korrekte Anweisungen enthalten: <fortran> MAX(dumdidum, R8_EPSILON) MAX(dumdidum, R4_EPSILON) </fortran> Korrekt ist aber: <fortran> MAX(dumdidum, 0.0D0) MAX(dumdidum, 0.0E0) </fortran>
Links
- Vergleich von Realwerten
- Aus dem Intel-Forum
- Guter Artikel über Problematik: The Perils of Floating Point