views:

123

answers:

1

I would have dared say that the numeric values computed by Fortran and C++ would be way more similar. However, from what I am experiencing, it turns out that the calculated numbers start to diverge after too few decimal digits. I have come across this problem during the process of porting some legacy code from the former language to the latter. The original Fortran 77 code...

  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

... outputs 0.842201471328735, while its C++ equivalent...

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

... returns 0.842201286195064. That is, the computed values are equal only up to the sixth decimal. Although not particularly a Fortran advocator, I feel inclined to consider its results as the 'correct' ones, given its legitimate reputation of number cruncher. However, I am intrigued about the cause of this difference between the computed values. Does anyone know what the reason for this discrepancy could be?

+8  A: 

In Fortran, by default, floating point literals are single precision, whereas in C/C++ they are double precision.

Thus, in your Fortran code, the expression for calculating NUMERATOR is done in single precision; it is only converted to double precision when assigning the final result to the NUMERATOR variable.

And the same thing for the expression calculating the value that is assigned to the DENOMINATOR variable.

janneb
Exactly. This is a common mistake -- the expression on the right hand side doesn't "know" that variable on the left is double precision. The FORTRAN 77 way to specify that a float constant is double precision is to add the suffix "D0" -- try that adding that to the legacy FORTRAN code.
M. S. B.
Thanks you both. Also, just for reference purposes, and as J.F. Sebastian has pointed out, -fdefault-real-8 can be used when compiling with gfortran in order to use double precision floating point literals.
plok