Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
29275 Discussions

Strange behavior converting strings to real numbers

Matthias_M_
Beginner
545 Views
Hello,

I observed some strange behavior converting very strings to real numbers when the resulting number is really 'huge'. A demo program is as follows:

program readtest
implicit none

INTEGER, PARAMETER :: DP = SELECTED_REAL_KIND(15,307)
CHARACTER (LEN=256) :: svalue
REAL(DP) :: dvalue

WRITE (svalue,*) HUGE(1.0_DP)
READ(svalue,*) dvalue

print *, dvalue

end program readtest


All tested versions of Intel Fortran for Linux (9.1.04, 10.0.025, 10.1.011, 10.1.012 and 10.1.015) compile well but yield the following error message:

forrtl: severe (64): input conversion error, unit -5, file Internal List-Directed Read
Image PC Routine Line Source
a.out 080996C3 Unknown Unknown Unknown
a.out 08098CE3 Unknown Unknown Unknown
a.out 080761BA Unknown Unknown Unknown
a.out 080657CA Unknown Unknown Unknown
a.out 08065465 Unknown Unknown Unknown
a.out 08050DCF Unknown Unknown Unknown
a.out 080500BB Unknown Unknown Unknown
a.out 08049D65 MAIN__ 9 readtest.f90
a.out 08049CB1 Unknown Unknown Unknown
libc.so.6 B7E0602C Unknown Unknown Unknown
a.out 08049BF1 Unknown Unknown Unkn own

Is this a bug in the READ routine?

Thank you very much for your help.

Matthias Mller
0 Kudos
3 Replies
Steven_L_Intel1
Employee
545 Views
No, it's a bug in your program. Rather, you make the mistaken assumption that the value written out using list-directed format is exactly the same as the binary value. List-directed rounds, and as it happens, it rounds this value up so that it is no longer in-range.

If you do this instead, it works:

WRITE (svalue,'(E27.19E3)') HUGE(1.0_DP)

The value is then stored in svalue as

0.1797693134862315708E+309

whereas the list-directed version is:

1.797693134862316E+308

Note the ...315708 which got rounded up to ...316.

Do not use list-directed formatting when it matters what format is used (or when you want to make assumptions about the validity of the input.)

In general, if you want a value converted to decimal and back again to have the same binary value, add at least three decimal digits to the number of digits representable in the data type.
0 Kudos
TimP
Honored Contributor III
545 Views
The number of decimal digits required to preserve a binary value with 53 bits precision would be log10(2_DP) * 53 + 2 in accordance with IEEE754. As Steve said, this may be as many as 3 more than the number of decimal digits of precision retainedwhen converting from decimal to binary to decimal. It would be unusual for a compiler to choose so many digits in list-directed formatting.
0 Kudos
joseph-krahn
New Contributor I
545 Views
C has an intersting solution to the problem of how to precisely print real numbers in a formatted output. It is seldom actually used, but the format %A will print floating point numbers in hexadecmial notation. The fractional part is written in standard hex, along with the base-2 exponent. It would be useful in some cases for Fortran to support this syntax. For now, one can always call a C function to do the formatting.
0 Kudos
Reply