1

I just wanted a second opinion. I am newer to gfortran and I have this code:

program Assignmenttwo
!Nik Wrye
!CDS251-001
!Homework #2/Assignment #2
!September 9th, 2021
    
!This program is to Next, write a do loop that iterates 10 million
!times. In the loop, add 1.e-7 (one ten-millionth) to each variable (The variable should
!appear on both sides of the equal sign.) After the loop, print out each variable with
!a label.
    
    implicit none
    !declaring variables
        
    real*4:: Numone, Numtwo
    !intializing variables
        
        Numone = 1.0
        Numtwo = 2.0
    
        do while (Numone < 1.1.and.Numtwo<2.1)!this do statement will cycle the loop until it has it the 10 millionth time
            
                Numone = Numone+1.e-7 !adding the desired amount
                Numtwo = Numtwo+1.e-7
        enddo   

        print*, Numone
        print*, Numtwo
        
    end program Assignmenttwo

I am expecting the output to be 1.1 and 2.1 but I am getting 1.1 and 2.0. Any ideas?

francescalus
  • 30,576
  • 16
  • 61
  • 96
Nik Wrye
  • 21
  • 6
  • What is the value of `nearest(2., 1.)` in your case? – francescalus Sep 03 '21 at 19:20
  • The assignment asked to make the first two variables 1.0 and 2.0, sorry for leaving that out. – Nik Wrye Sep 03 '21 at 19:22
  • 1
    Floating-point numbers have a limited dynamic range - the larger the absolute value of the number, the less precision you have. Starting with 1.0, 1e-7 is about the smallest value you can add and still have a different result. Starting with 2.0, 1e-7 is *too small to represent* - the result of the addition is still 2.0. Using `real*8` variables would be a solution here. – jasonharper Sep 03 '21 at 19:24
  • Ahhh thank you. I was starting to notice this. Great to have confirmation, I think this may have been the point to the assignment haha, thanks! – Nik Wrye Sep 03 '21 at 19:27
  • You aren't looping 10 million times, you are looping until they increasing by 0.1, which would be only a 1 million iterations. And doing it with a while loop will cause problems as jasonharper suggests (the loop should never end since Numtwo will stay as 2.0, so the condition should never be met). I expect the point of the assignment was to demonstrate that numtwo wouldn't increase, but numone would. – Tyberius Sep 03 '21 at 19:28
  • I hope your teacher isn't telling you to use real*4 - that isn't and has never been part of standard Fortran. Kinds are the way to go, see https://stackoverflow.com/questions/838310/fortran-90-kind-parameter – Ian Bush Sep 03 '21 at 19:29
  • He explicitly stated that we use real*4 for this assignment, and the next question he has on the assignment is to explain the limitations. – Nik Wrye Sep 03 '21 at 19:31
  • 1
    This is _surely_ a duplicate of some more general (non-Fortran) f-p question, but I couldn't see an obvious one that's Fortran-friendly. – francescalus Sep 03 '21 at 19:43
  • See also a [different aspect](https://stackoverflow.com/q/58257412/3157076) of this. – francescalus Sep 03 '21 at 19:54

1 Answers1

1

Arguably the point of this assignment is that you get 1.1 but 2.0. This is down to the behaviour of floating point, the full details of which you can read about elsewhere.

You can do the simple test

print *, 1.+1e-7, 2.+1e-7
print *, 1.+1e-7/=1., 2.+1e-7/=2.

without doing the loops to see the effect.

Instead of repeating massive detail about the mechanics, I'll just mention that you can confirm that 1e-7 is "too small" to have an effect by using the nearest intrinsic function

print *, nearest(2., 1.)

With double precision you'll get different answers. (And this is why careful consideration of which real type to use in any case is important.)

Don't forget that Fortran no longer allows real DO control where increments may indeed be too small to have an effect.

francescalus
  • 30,576
  • 16
  • 61
  • 96