2010-05-03 13 views
6

berechneten Werten Ich hätte es gewagt, zu sagen, dass die von Fortran und C++ berechneten numerischen Werte viel ähnlicher wären. Wie sich jedoch herausstellt, beginnen die berechneten Zahlen nach zu wenigen Dezimalstellen zu divergieren. Ich bin auf dieses Problem während der Portierung einiger Legacy-Codes von der früheren auf die letztere Sprache gestoßen. Der ursprüngliche Fortran 77 Code ...Diskrepanz zwischen den von Fortran und C++

INTEGER M, ROUND 
    DOUBLE PRECISION NUMERATOR, DENOMINATOR 

    M = 2 
    ROUND = 1 
    NUMERATOR=5./((M-1+(1.3**M))**1.8) 
    DENOMINATOR = 0.7714+0.2286*(ROUND**3.82) 
    WRITE (*, '(F20.15)') NUMERATOR/DENOMINATOR 
    STOP 

... Ausgänge 0,842201471328735, während die C++ Äquivalent ...

int m = 2; 
int round = 1; 
long double numerator = 5.0/pow((m-1)+pow(1.3, m), 1.8); 
long double denominator = 0.7714 + 0.2286 * pow(round, 3.82); 
std::cout << std::setiosflags(std::ios::fixed) << std::setprecision(15) 
      << numerator/denominator << std::endl; 
exit(1); 

... kehrt 0,842201286195064. Das heißt, die berechneten Werte sind gleich nur bis zur sechsten Dezimalzahl. Obwohl ich kein Fortran-Befürworter bin, fühle ich mich geneigt, seine Ergebnisse als die "richtigen" zu betrachten, angesichts seines legitimen Rufs als Number Cruncher. Ich bin jedoch über die Ursache dieses Unterschieds zwischen den berechneten Werten fasziniert. Weiß jemand, was der Grund für diese Diskrepanz sein könnte?

+1

http://docs.sun.com/source/806-3568/ncg_goldberg.html –

+0

C++ Ergebnis ist richtiger '0.8422012861950640318689334181' – jfs

+0

Vielleicht könnten Sie in beiden Sätzen von Code einige Zwischenwerte ausdrucken. –

Antwort

11

In Fortran sind Fließkomma-Literale standardmäßig eine einfache Genauigkeit, während sie in C/C++ doppelt genau sind.

Daher wird in Ihrem Fortran-Code der Ausdruck für die Berechnung von NUMERATOR in einfacher Genauigkeit ausgeführt; Es wird nur in doppelte Genauigkeit konvertiert, wenn das Endergebnis der Variablen NUMERATOR zugewiesen wird.

Und das gleiche für den Ausdruck, der den Wert berechnet, der der DENOMINATOR-Variablen zugewiesen wird.

+1

Genau. Dies ist ein häufiger Fehler - der Ausdruck auf der rechten Seite "kennt" diese Variable auf der linken Seite nicht mit doppelter Genauigkeit. Die FORTRAN 77-Methode zum Angeben einer Float-Konstante mit doppelter Genauigkeit besteht darin, das Suffix "D0" hinzuzufügen - versuchen Sie, das dem Legal-FORTRAN-Code hinzuzufügen. –

+0

Danke euch beiden. Auch nur zu Referenzzwecken, und wie J. F. Sebastian darauf hingewiesen hat, kann -fdefault-real-8 verwendet werden, wenn mit gfortran kompiliert wird, um Gleitkomma-Literale mit doppelter Genauigkeit zu verwenden. – plok

+0

Ich weiß, dass dies ein alter Thread ist, aber ich habe heute etwas sehr wertvolles gelernt, das eine Diskrepanz behebt, die wir in unserem Code haben. Danke @ M.S.B. für die "D0" Spitze. – jitihsk

Verwandte Themen