floating-point fortran gfortran

floating point - ¿Error matemático simple en gfortran?



floating-point (3)

Soy un principiante con respecto a la programación en Fortran. Actualmente estoy usando cygwin y el compilador gfortran que se ejecuta en mi PC con Windows XP. Estoy teniendo dificultades con algunas matemáticas simples: el programa que escribí simplemente no hará las matemáticas. El código es:

program convert real t t=0 t=8320671.25 - 8000000.00 write(*,*) t end

¡El programa debería darme la respuesta "320671.25" pero en su lugar me da 320671.00! ¿Qué estoy haciendo mal?


Aquí hay un ejemplo trabajado usando la sugerencia de High Performance Mark. El tipo "8" no es una forma portátil de especificar reales de doble precisión. La mayoría de los compiladores ahora admiten los tipos de entorno ISO Fortran utilizados en el ejemplo. Si tiene un compilador anterior, puede utilizar el ISO_C_BINDING y el tipo c_double , que han estado disponibles por más tiempo. Como Evert hizo, es esencial especificar los tipos de las constantes. El cálculo se realiza en el RHS, luego la asignación se hace a la variable en el LHS. No es suficiente que la variable en el LHS tenga suficiente precisión.

program convert use, intrinsic :: ISO_FORTRAN_ENV real (real64) :: t t=8320671.25_real64 - 8000000.00_real64 write(*,*) t end program convert


Aunque no importa el ejemplo que usted dio, si hubiera una mayor disparidad en las magnitudes de los operandos, reemplace

real t

con

double precision t

De lo contrario, la diferencia se truncaría al almacenamiento disponible.

Para su ejemplo, la precisión de las constantes es demasiado pequeña. Un valor de coma flotante dado como usted tiene ( 8320671.25 y 8000000.00 ) es de tipo real que especifica "precisión simple": que usa una representación de valores de punto flotante de 32 bits que son equivalentes a 6 a 7 dígitos decimales de precisión . Double precision es (desde la década de 1980) generalmente una representación de coma flotante de 64 bits, equivalente a 15 a 17 dígitos decimales . Sin embargo, algunas implementaciones pueden optar por implementar la double precision la misma manera que una real , aunque en las máquinas que cumplen con IEEE-754, por lo general es más grande.

Para hacer que un punto flotante sea constante doble, escriba una D para el exponente:

t = 8320671.25D0 - 8000000.00

Tenga en cuenta que hacer operandos posteriores de double precision no funcionará debido a las reglas de escritura de expresiones de Fortran:

t = 8320671.25 - 8000000.00D0 ! Wrong! Result is "real"

o

t = 8320671.25 - 8D6 ! Wrong! Result is "real"

El primer ejemplo produce la salida 320671.250 . Los demás producen 320671.000 (si t es tipo real ) o 320671.00000000000 si t es de tipo double precision .

Desde la década de 1940, Fortran se ha implementado en diversas arquitecturas. En algunos de ellos (VAX, por ejemplo), las opciones de compilación de línea de comando especifican qué tipo de hardware se usa para real y para double precision . La arquitectura de DEC tenía al menos cuatro sabores de punto flotante (F-Float, D-Float, G-Float y H-Float), todos los cuales fueron diseñados mucho antes que IEEE-754. Consulte esto para obtener una perspectiva histórica del desarrollo de IEEE-754.


Estás corriendo en el límite de precisión simple. El resultado de la resta es un real*4 y se puede almacenar de forma segura en t . Los valores utilizados en la resta, sin embargo, están fuera del rango real*4 . Fuera en el rango de precisión, con el resultado de que los números se redondean para encajar en un real*4 antes de calcular la resta.

Prueba esto por ejemplo:

program convert real t t=0 t=8320671.25_8 - 8000000.00_8 write(*,*) t end

El _8 adjunto asegura que los dos números son de doble precisión; el resultado se convierte a real antes de asignarse a t , pero el cálculo ahora es de doble precisión y el .25 se "guarda" en la resta.