2010-05-03 15 views
6

Me atrevería a decir que los valores numéricos calculados por Fortran y C++ serían mucho más similares. Sin embargo, por lo que estoy experimentando, resulta que los números calculados comienzan a divergir después de muy pocos dígitos decimales. Me he encontrado con este problema durante el proceso de transferir algún código heredado del idioma anterior a este último. El código original de Fortran 77 ...Discrepancia entre los valores calculados por Fortran y 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 

... salidas ,842201471328735, mientras que su equivalente en 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); 

... vuelve ,842201286195064. Es decir, los valores calculados son iguales a solo hasta el sexto decimal. Aunque no soy particularmente un defensor Fortran, me siento inclinado a considerar sus resultados como los 'correctos', dada su reputación legítima de número cruncher. Sin embargo, estoy intrigado sobre la causa de esta diferencia entre los valores calculados. ¿Alguien sabe cuál podría ser el motivo de esta discrepancia?

+1

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

+0

C++ resultado es más correcto '0.8422012861950640318689334181' – jfs

+0

tal vez usted podría imprimir algunos valores intermedios en los dos conjuntos de código. –

Respuesta

11

En Fortran, por defecto, los literales de punto flotante son de precisión simple, mientras que en C/C++ son de doble precisión.

Por lo tanto, en su código Fortran, la expresión para calcular NUMERATOR se hace en una sola precisión; solo se convierte en doble precisión al asignar el resultado final a la variable NUMERATOR.

Y lo mismo ocurre con la expresión que calcula el valor asignado a la variable DENOMINATOR.

+1

Exactamente. Este es un error común: la expresión del lado derecho no "sabe" que la variable de la izquierda es de doble precisión. La forma de FORTRAN 77 de especificar que una constante de flotación es de doble precisión es agregar el sufijo "D0"; intente agregar eso al código FORTRAN heredado. –

+0

Gracias a los dos. Además, solo con fines de referencia, y como ha señalado J.F. Sebastian, -fdefault-real-8 se puede usar al compilar con gfortran para usar literales de coma flotante de precisión doble. – plok

+0

Sé que este es un hilo antiguo, pero aprendí algo muy valioso hoy que corrige una discrepancia que tenemos en nuestro código. Gracias @ M.S.B. para la punta "D0". – jitihsk

Cuestiones relacionadas