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?
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.
@avinashs, .. the value assigned by Fortran when read from the file is x = 50.8002001953125 ..
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:
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>
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.
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