问题
I installed gfortran on my Ubuntu 15.04 system. While compiling Fortran code, the DO loop asks to take integer parameters only and not real values or variables. That includes the loop variable and the step expression. Why can't it take real values too?
The following is a program taken from here, exercise 3.5 of the section nested do loops.
program xytab
implicit none
!constructs a table of z=x/y for values of x from 1 to 2 and
!y from 1 to 4 in steps of .5
real :: x, y, z
print *, ' x y z'
do x = 1,2
do y = 1,4,0.5
z = x/y
print *, x,y,z
end do
end do
end program xytab
The error shown after compiling is:
xytab.f95:8.4:
do y = 1,4,0.5
1
Warning: Deleted feature: Loop variable at (1) must be integer
xytab.f95:8.12:
do y = 1,4,0.5
1
Warning: Deleted feature: Step expression in DO loop at (1) must be integer
xytab.f95:7.3:
do x = 1,2
1
Warning: Deleted feature: Loop variable at (1) must be integer
回答1:
The Fortran standard now requires that a do construct's loop control is given by (scalar) integer expressions and that the loop variable is a (scalar) integer variable. The loop control consists of the start, step, and stop expressions (your step expression is 0.5
). See R818 and R819 (8.1.6.2) of the Fortran 2008 document. That, then, is the short and simple answer: the standard says so.
It's a little more complicated than that, as the messages from the compiler suggest. Using other forms for loop control was present in Fortran up until Fortran 95. That is, from Fortran 95 onward using real expressions is a deleted feature.
What harm is there in using real expressions? Used correctly, one could imagine, there is no harm. But there's real difficulty in portability with them.
Consider
do x=0., 1., 0.1
...
end do
How many iterations? That would be (under the rules of Fortran 90) MAX(INT((m2 – m1 + m3) / m3), 0)
where (m1
is the start value (0.
), m2
the stop value (1.
) and m3
the step value (0.1
)). Is that 10 or 11 (or even 9)? It depends entirely on your numeric representation: we recall that 0.1
may not be exactly representable as a real number and INT
truncates in converting to integer. You'd also have to worry about repeated addition of real numbers.
So, use integers and do some arithmetic inside the loop
do y_loop = 0, 6
y = 1 + y_loop/2.
...
end do
or
y = 1
do
if (y>4) exit
...
y = y+0.5
end do
Finally, you mention .f90
and .f95
file suffixes. gfortran doesn't take the first to mean that the source code follows the Fortran 90 standard (where the code would be fine). Further, the messages from the compiler are merely warnings, and these can be suppressed using the -std=legacy
option. Conversely, using -std=f95
(or later standards) these become errors.
As a bonus fun fact consider the following piece of Fortran 90 code.
real y
integer i
loop_real: do y=1, 4, 0.5
end do loop_real
loop_integer: do i=1, 4, 0.5
end do loop_integer
While the loop named loop_real
is valid, that named loop_integer
isn't. In the calculation of the iteration count the three expressions are converted to the kind, with kind parameters, of the loop variable. INT(0.5)
is 0
.
来源:https://stackoverflow.com/questions/30707668/fortran-do-loop-warning-to-use-integer-only