2

In the code below I am adding together 865398.78 and -865398.78. I expect to get 0, but instead I get -0.03.

The Fortran code and the result

Source Code:

program main
real(8) :: x

open(10,file="test.txt")
read(10,*)x
print *,"x=",x
x=x+865398.78
print *,"x+865398.78=",x
end program

Result:

x=  -865398.780000000     
x+865398.78= -3.000000002793968E-002

Am I wrong with the usage of "read" codes or something else?

francescalus
  • 30,576
  • 16
  • 61
  • 96
ke xu
  • 131
  • 5
  • 2
    I have in-lined your image, but it may be better if you could look at converting it into plain text (you already have the source code here, but the input file would be better as text). I've also paraphrased the question (and assumed that you expect 0 as the result) into the body: if you aren't happy with what I've done then you can revert my edit. – francescalus Oct 24 '15 at 15:06

2 Answers2

5

The number 865398.78 is represented in single precision in your code. Single precision can handle about 7 significant digits, while your number has 8. You can make it double precision by writing

x=x+865398.78_8
Raul Laasner
  • 1,475
  • 1
  • 17
  • 30
  • 3
    In this answer, `8` is a kind parameter, and typically refers to double precision. But double precision is *not* always 8, and using 8 to define double precision is outdated. – Ross Oct 24 '15 at 18:35
  • 3
    Adding on to @Ross, `d0` would be a more appropriate suffix to convert the number to double precision, that is, `865398.78d0`. – jyalim Oct 24 '15 at 18:53
  • @Ross and @HAL 9001 Thanks for the comments. `8` is indeed not always dp. The idea is to use the same kind as in the declaration of `x`, whatever it is for a given compiler. Personally, I only use the `iso_fortran_env` constants. – Raul Laasner Oct 24 '15 at 19:57
4

I will make one big assumption in this answer: that real(8) corresponds to double precision.

You are probably assuming that your 865398.78 means the same thing wherever it occurs. In source code that is true: it is a default real literal constant which approximates 865398.78.

When you have

x=x+865398.78

for x double precision, then the default real constant is converted to a double precision value.

However, in the read statement

read(10,*)x

given input "-865398.78" then x takes a double precision approximation to that value.

Your non-zero answer comes from the fact that a default real/single precision approximation converted to a double precision value is not in general, and isn't in this case, the same thing as an initial double precision approximation.

This last fact is explained in more detail in other questions. As is the solution to use x=x+865398.78_8 (or better, don't use 8 as the kind value).

Community
  • 1
  • 1
francescalus
  • 30,576
  • 16
  • 61
  • 96