Community
cancel
Showing results for 
Search instead for 
Did you mean: 
avinashs
New Contributor I
83 Views

Use of the Intel Fortan compilation option /real-size:64

I a number stored in a text file as 50.8, but the value assigned by Fortran when read from the file is x = 50.8002001953125. Is there a way around this problem? Will the compilation option /real-size:64 prevent the noise artificially introduced into the variable?

0 Kudos
4 Replies
Steve_Lionel
Black Belt Retired Employee
70 Views

It's not "noise" - it's that 50.8 cannot be exactly represented in a binary floating-point format. In single-precision it is hex 424B3333.

Double-precision will get you a bit closer - the hex form is 4049666666666666 but the decimal form is 50.79999999999999716.

 
FortranFan
Honored Contributor I
65 Views

 

@avinashs,
.. the value assigned by Fortran when read from the file is x = 50.8002001953125 ..

 

 

@avinashs ,

You would have noticed the above the difference is way too high with any of the usual binary floating-point representation aspects; any number of tools online can show you that with the binary (or hex) representation of the constant.

Under the circumstances, please always consider a minimal working example you can share to illustrate the problem - chances are rather high you will figure out the issue and the solution yourself in the process, thereby empowering you considerably. 

You will note there is little the readers can do otherwise to really help, for they will be left to wonder what may be going on as you can see below:

datafile: "x.dat"

 

50.8

 

Fortran code: "p.f90"

 

   character(len=*), parameter :: fmtg = "(g0,1x,1pg23.16)" 
   character(len=*), parameter :: fmth = "(g0,1x,z0)" 
   blk1: block
      integer, parameter :: WP = selected_real_kind( p=6 )
      real(WP) :: x
      integer :: lun
      print *, "Block 1: with decimal precision of ", precision(x)
      open( newunit=lun, file="x.dat", status="old", form="formatted" )
      read( lun, fmt=* ) x
      print fmtg, "x =     ", x
      print fmth, "x(hex): ", x
      close( lun )
   end block blk1
   print *
   blk2: block
      integer, parameter :: WP = selected_real_kind( p=12 )
      real(WP) :: x
      integer :: lun
      print *, "Block 2: with decimal precision of ", precision(x)
      open( newunit=lun, file="x.dat", status="old", form="formatted" )
      read( lun, fmt=* ) x
      print fmtg, "x =     ", x
      print fmth, "x(hex): ", x
      close( lun )
   end block blk2
end

 

Program using Intel Fortran:

 

C:\Temp>ifort /standard-semantics p.f90
Intel(R) Fortran Intel(R) 64 Compiler Classic for applications running on Intel(R) 64, Version 2021.1.2 Build 20201208_000000
Copyright (C) 1985-2020 Intel Corporation.  All rights reserved.

Microsoft (R) Incremental Linker Version 14.26.28806.0
Copyright (C) Microsoft Corporation.  All rights reserved.

-out:p.exe
-subsystem:console
p.obj

C:\Temp>p.exe
 Block 1: with decimal precision of  6
x =        50.79999923706055
x(hex):  424B3333

 Block 2: with decimal precision of  15
x =        50.80000000000000
x(hex):  4049666666666666

C:\Temp>

 

 

Arjen_Markus
Valued Contributor III
48 Views

Compare it to representing 1/3 as a decimal number: 1/3 is (approximately) 0.3333333... The reason you can represent 508/10 in a decimal form with a finite number of decimals is that the denominator only contains the same factors 2 and 5 as the radix 10 of the decimal system. In the same way 1/2, 1/8, 1/1024 or 1/625 are representable via a finite number of decimals.

The binary representation used by most computers only contains the factor 2.

mecej4
Black Belt
41 Views

Avinash,

Here is a short program to reinforce what FF and Arjen have explained. Compile and run, and explain the result that is printed. Change "REAL" to "DOUBLE PRECISION", and repeat.

On a hypothetical CPU that used 3 as the base of the number system, what would the answer have been?

program fpe
   real :: x = 4
   print *,1-(x/3-1)*3
end program fpe