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

Internal Read and Write

gelarimer
Beginner
780 Views

REAL RPM1, RPM2
CHARACTER(10) sRPM

! e.g., 100.234 to 100.24
RPM1 = CEILING(RPM1*100.0)/100.0

WRITE(sRPM, '(F6.2)', IOSTAT = iErr) RPM1

READ(sRPM, '(F6.2)', IOSTAT = iErr) RPM2

For a win32 app, will the internal representation of RPM1 always equal the internal representation of RPM2? In other words, willRPM1 and RPM2 have exactly the same 32 bit representation in memory?

The reason: I would like to performcalcs using RPM1 and write sRPM to a disc file. At some future time open the app again, read sRPM from a disc file,perform calcs, and get exact answer without any chance of real number round off in memory.

Thanks for any info.

0 Kudos
10 Replies
Steven_L_Intel1
Employee
780 Views
Definitely not with an F6.2 format. I think you need at least ten decimal digits to guarantee the same binary value for a single precision REAL. If you don't mind it not being human readable, a Z8.8 format would work as well.
0 Kudos
anthonyrichards
New Contributor III
780 Views

Since a REAL*4 variable can store four 8-bit bytes, this corresponds to 4 characters, so you could also save the bit-pattern as a 4-character variable I think.

0 Kudos
Steven_L_Intel1
Employee
780 Views
That would not be a good idea as some bit patterns might be misinterpreted by formatted reads.
0 Kudos
gelarimer
Beginner
780 Views

Thanks for the replies, but do not understand how F6.2 impacts on value in memory. I assumed thatusing two different methods to get RPM1 and RPM2, CEILING() vs an internal read(), would be the major contributor to small differences in memoryinary representation.

RPM1 = 100.24
sRPM = '100.24 '
RPM2 = 100.24

Also looked at Z8.8 format and that appears good for transferring INTEGERs, but not sure how that applies to real numbers RPM1 and RPM2.

If I use RPM2from the interal read()andwrite sRPM to disc file at same time, then at some future date start the app and read sRPM from discinto RPM2 then, hopefully, calculated values should be indentical for the 1st and 2nd runs of the app. Is this correct, or amI missing something?

0 Kudos
jimdempseyatthecove
Honored Contributor III
780 Views

The problem you will encounter is several decimal fractions e.g. 0.1 is a repeating binary fraction that cannot be exactly represented. If your RPMs are always carried to two places then consider computing and storing the numbers as centaRPMs with no fraction.

Or, any time you CEILING the RPM to fix the precision perform your save to file:

RPM1 = CEILING(RPM1*100.0)
WRITE(sRPM, '(F6.0)', IOSTAT=iERR) RPM1
... (LATER)
READ(sRPM, '(F6.0)', IOSTAT=iERR) RPM2
RPM2 = RPM2 / 100.0

In this manner you will not loose precision performing the formatted write and later the formatted read. Your other option would be to write as binary formatted files. But this may introduce portability issues.

Jim Dempsey

0 Kudos
Steven_L_Intel1
Employee
780 Views

Z8.8 works for REALs too - it just stores the 32-bit binary value in hexadecimal.

As Jim says, many decimal fractions cannot be exactly represented in binary floating point. In order to get the same binary representation, you need to write and read several more decimal digits than the precision of the datatype.

I suggest reading the series of three articles "The Perils of Real Numbers" in the Newsletter thread.

0 Kudos
gelarimer
Beginner
780 Views
I have reviewed the 3 articles on "The Perils of Real Numbers' and they were helpful.Still a little confused however, so I will take another look at the articles and the IVF Language Reference.Thanks forthereplies.
0 Kudos
gelarimer
Beginner
780 Views

Starting to understand:

1) RPM1 may or may not be represented exactly in memory
2) if RPM1 is not exactly represented, then the F6.2 format will round updown
3) RPM2 abtained from the internal read() also may or may not be represented exactly in memory
4) so RPM1 may or may not = RPM2

So,to obtain sameresults for different rumssessions of program:

1) RPM1 = CEILING(.........
2) write(sRPM....) RPM1
3) read(sRPM....) RPM1 and use for current calcs
4) write() sRPM to disc file during current session
3)nextsessionread sRPMfrom disc into RPM1 and calcs should be resonably the same, hopefully with the same7 significant digits

0 Kudos
jimdempseyatthecove
Honored Contributor III
780 Views

The point of your write is to provide a snapshot of the calculations. Presumably such that should an abnormal termination occur (due to coding problem innon-critical to solution or power outage, of disk full, etc...) that you then have an opportunity to correct the problem and then resume the calculations (as if the problem did not occur).

I am making an assumption for the following

If your code is designed to periodically coerce the data to a given precision by way of something like

RPM1 = CEILING(RPM1*100.0)/100.0

And if at that point you also decide to checkpoint the data

RPM1 = CEILING(RPM1*100.0)/100.0
WRITE(....) RPM1

And then later, if necessary due toabnormal endof program, read back the data to resume calculation.

Then your resumption will not alway be precisely the same. This is due to the "/100.0" on the CEILING statment potentially producing repeating, and truncated, binary fractions that when written to a file using F6.2 (or whatever) may experience an additional truncation. Then upon a resumption, resuming with a slightly different value.

The more accurate route would be to perform the snapshot when the data is known to be recordable and restorable to the precision desired.

In this case, if you perform the snapshot between the CEILING(RPM1*100.0) and the "/100.0" the data written and the data read will convey the exact same binary data.

An alternate way is to record the data in binary format.

Jim Dempsey


0 Kudos
gelarimer
Beginner
780 Views
Thanks Jim. The replies and info above has helped a great deal.
0 Kudos
Reply