Ist es möglich, Having mit NaN eine Parametervariable zu setzen? und habe das in einem bestimmten Modul. Ich möchte es für die Initialisierung einiger anderer Variablen verwenden. Daher werde ich mit einem Laufzeitfehler konfrontiert werden, wenn sie nicht aktualisiert werden, anstatt Simulationen, die mit einigen Zufallszahlen ausgeführt werden. Ich benutze GFORTRAN.Parameter (konstanten) Variable mit NaN Wert in Fortran
Antwort
Es ist möglich. Sie müssen zuerst herausfinden, welches Bitmuster einen der möglichen NaN-Werte darstellt. Sie können die Bitmuster in einer ganzen Zahl speichern:
use, intrinsic :: iso_fortran_env
real(real64) x
integer(int64) i
x = 0
x = 0/x
print *, x
print *, transfer(x, i)
end
Es gibt: -2251799813685248
Dann Sie Ihre Variablen mit
real(real64), parameter :: nan64 = transfer(-2251799813685248_int64, 1._real64)
Ähnliches gilt für 32-Bit-Variablen initialisieren können Sie die ganze Zahl erhalten - 4194304, so dass Sie tun können
real(real32), parameter :: nan32 = transfer(-4194304_int32, 1._real32)
Viele Compiler haben eine Option zu tun das für Sie für alle echten Variablen. Wie francescalus zeigt in gfortran ist es -finit-real=nan
. Wenn Sie das manuell tun, erhalten Sie eine feinere Kontrolle.
Haftungsausschluss: Seien Sie vorsichtig, wenn auf eine andere Plattform wechseln. Endianness und andere Themen könnten eine Rolle spielen, obwohl ich denke, dass es tatsächlich in Ordnung sein könnte. Ich nahm eine IEEE-konforme CPU an.
Siehe, Francescalus 'Antwort für eine Alternative, die eine Standardfunktion verwendet. Leider ist es nicht für parameter
Konstanten anwendbar, ist aber nützlich.
Ich stimme Ihrem Vorschlag @Vladimir F auf diese Weise während der Laufzeit ist es möglich, Wert einer Variablen zu NaN zu ändern oder umgekehrt. Der Nachteil ist jedoch das maschinenabhängige Bitmuster von NaN. – Sorush
Um zu Vladimir F's answer hinzufügen werde ich erwähnen, dass gfortran 5.0 (aber nicht früher) die IEEE intrinsische Module unterstützt.
Statt
real x
x=0
x=0/x
man kann
use, intrinsic :: iso_fortran_env
use, intrinsic :: ieee_arithmetic
integer(int32) i
real(real32) x
x = ieee_value(x, ieee_quiet_nan)
i = transfer(x,i)
verwenden Dies gibt Ihnen ein wenig Flexibilität, über die der NaN Werte, die Sie erhalten. Sie müssen sich auch keine Gedanken über ungültige Flags für die Signalisierung machen. [Bitte beachten Sie, dass die Frage nach ieee_signaling_nan
Sie möglicherweise nicht wirklich geben kann.]
Beachten Sie, dass ieee_value()
nicht direkt in der Initialisierung verwendet werden kann: eine Referenz darauf ist kein konstanter Ausdruck. Für diesen Zweck verwenden Sie diesen Ansatz, um das Bitmuster zu erhalten und die Methode der anderen Antwort anzuwenden.
Sie müssen auch sicherstellen, dass die Unterstützung für jeden Datentyp für die Funktionen ist.
Es stimmt, ich ging noch nicht zu viel in diesen, wie ich die Kompatibilität mit gfortran 4.8 halten müssen. Leider ist 'ieee_value' in konstanten Ausdrücken in der Tat nicht erlaubt, also muss man noch transfer() verwenden. Viel mehr Diskussion ist in https://groups.google.com/forum/#!msg/comp.lang.fortran/tYC3UgAyNrY/6TzOLbkP6tsJ –
Es scheint, wenn ich NaN für das Debuggen und immer Laufzeitfehler verwenden will, muss ich NaN eher als die ruhigste zu verwenden Signalisierung ([Ref] (http://stackoverflow.com/questions/18118408/what-is-difference-between-quiet-nan-and-signaling-nan)). – Sorush
@Sorush Ja. Es gibt keine Garantie dafür, dass "ieee_signaling_nan" zu so etwas führt (obwohl es empfohlen wird). Ich habe keine Ahnung, was Gfortran zurückgibt - wenn Sie testen können, lassen Sie es mich wissen. Ein stilles NaN ist immer noch wertvoll, in gewisser Hinsicht: Du weißt, dass etwas schiefgelaufen ist. Nicht zum Debuggen geeignet. – francescalus
Wenn Sie mit einem GFortran stecken, der nicht über das eingebaute IEEE verfügt, aber über das iso_c_binding verfügt (wie das zum Erstellen von R unter Windows), funktioniert das folgende und entspricht dem C und R NaN (erfüllt is.nan
auf R): Interessanter
real(kind = c_double), parameter :: ONE = 1_c_double
real(kind = c_double), parameter :: NAN = TRANSFER(z'7FF0000000000001', ONE)
versagt real(kind = c_double), parameter :: NAN = TRANSFER(z'7FF0000000000001', 1_c_double)
meinen Scheck für is.nan
.
Ist Ihnen bekannt, dass '1_c_double' eine Ganzzahl ist? Nachdem Sie erkannt haben, dass Sie das nicht mehr so interessant finden, werden Sie es nicht mehr finden. Ihre erste Zeile kann nur 'real (art = c_double), Parameter :: ONE = 1' sein und es wird dasselbe tun. Siehe meine Antwort für die richtige Syntax für Reals. –
Also am Ende können Sie verkürzen es nur 'real (c_double), Parameter :: NAN = TRANSFER (z'7FF0000000000001' , 1._c_double)' oder 'real (c_double), Parameter :: NAN = TRANSFER (9218868437227405313_c_int64_t, 1._c_double) ' –
@VladimirF, Danke. – Avraham
Für gfortran, würde ich versucht sein, nur zu betrachten '-finit-real = nan'. – francescalus