2010-05-03 8 views
6

J'aurais osé dire que les valeurs numériques calculées par Fortran et C++ seraient beaucoup plus similaires. Cependant, d'après ce que je vis, il s'avère que les nombres calculés commencent à diverger après trop peu de chiffres décimaux. J'ai rencontré ce problème pendant le processus de portage du code hérité de l'ancienne langue vers le second. L'original Fortran 77 ...Discordance entre les valeurs calculées par Fortran et 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 

... sorties ,842201471328735, tandis que son équivalent C++ ...

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); 

... retourne ,842201286195064. C'est-à-dire que les valeurs calculées sont égales à jusqu'à la sixième décimale. Bien que n'étant pas particulièrement un avocat Fortran, je suis enclin à considérer ses résultats comme les «vrais», compte tenu de sa réputation légitime de cruncher. Cependant, je suis intrigué par la cause de cette différence entre les valeurs calculées. Est-ce que quelqu'un sait ce que la raison de cet écart pourrait être?

+1

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

+0

C++ résultat est plus correct '0.8422012861950640318689334181' – jfs

+0

Peut-être que vous pouvez imprimer quelques valeurs intermédiaires dans les deux ensembles de code. –

Répondre

11

Dans Fortran, par défaut, les littéraux à virgule flottante sont à simple précision, tandis qu'en C/C++, ils sont à double précision. Ainsi, dans votre code Fortran, l'expression pour calculer NUMERATOR est faite en simple précision; il est seulement converti en double précision lors de l'attribution du résultat final à la variable NUMERATOR.

Et la même chose pour l'expression calculant la valeur affectée à la variable DENOMINATOR.

+1

Exactement. C'est une erreur courante - l'expression sur le côté droit ne "sait" pas que la variable sur la gauche est double précision. La méthode FORTRAN 77 pour spécifier qu'une constante flottante est double précision consiste à ajouter le suffixe "D0" - essayez d'ajouter cela au code FORTRAN hérité. –

+0

Merci à vous deux. Aussi, juste à titre de référence, et comme l'a souligné J.F. Sebastian, -fdefault-real-8 peut être utilisé lors de la compilation avec gfortran pour utiliser des littéraux en virgule flottante en double précision. – plok

+0

Je sais que c'est un vieux fil de discussion, mais j'ai appris quelque chose de très précieux aujourd'hui qui corrige un désaccord que nous avons dans notre code. Merci @ M.S.B. pour l'embout "D0". – jitihsk