0

I have the following fortran code defined under. I am trying to change the length of the do loop if i change the value of n. When i try to compile i get the error:
‘a’ argument of ‘floor’ intrinsic at (1) must be REAL. But when i change q and w to be defined as real i get another error message. How can i fix this? q and w is clearly a integer when i use floor(...)

subroutine boundrycon(n,bc,u,v)


!input
integer :: n,bc

!output
real(8) :: u(n+2,n+2), v(n+2,n+2)

!lokale
integer :: j,i,w,q

n=30

q=floor(n/2)
w=(floor(n/2)+floor(n/6))


do j=q,w  
u(q,j)=0.0;
v(q+1,j)=-v(q,j);

u(w,j)=0.0;
v(w+1,j)=-v(w,j);

end do

do i=q,w 

v(i,q)=0.0;
u(i,q)=-u(i,q+1);


u(i,w+1)=-u(i,w);
v(i,w)=0;

end do

end subroutine boundrycon
euroshopper
  • 81
  • 1
  • 1
  • 9
  • `q` is clearly an integer because it is _declared_ as an integer, not because it is assigned an integer function result. The argument to `floor` is, in the first one, an integer, and that is the problem. `q` isn't the argument to the function: `n/2` is. [`n/2` is integer, for `n` an integer.] You are, then, asking, how to have `n/2` as a real? – francescalus Mar 16 '16 at 19:04
  • The result of integer division `n/2` ( for positive `n` ) IS the "floor" of the division, so you most likely just don't need the intrinsic `floor` function here at all. – agentp Mar 16 '16 at 19:33
  • n/2=15, but if i change n to 45 for example, 45/2=22.5 The whole point is when i change n i change the do loop length. I am asking why i get an error when i compile, even though q and w is an integer, and i have fulfilled the requirements for a do loop. – euroshopper Mar 16 '16 at 19:43
  • 1
    The error isn't about `q`, it's about `floor(n/2)`. `n/2` [is an integer](http://stackoverflow.com/a/24488741) (and as @agentp says, the flooring is redundant) and one cannot pass an integer to floor. If you must keep flooring, try `floor(n/2.)` which has a real argument. – francescalus Mar 16 '16 at 19:47
  • It worked when i only used q=n/2 and w=n/2+n/6. Even when i changed n to 45. It seems that fortran turns a real number 45/2 into a integer on its own. Even though i found that strange. Does anybody know if that is correct? – euroshopper Mar 16 '16 at 22:42

1 Answers1

1

Many people have already pointed this out in the comments to your question, but here it is again as an answer:

In Fortran, if you do a division of two integer values, the result is an integer value.

6/3 = 2

If the numerator is not evenly divisible by the denominator, then the remainder is dropped:

7/3 = 2

Let's look at your code:

q=floor(n/2)

It first evaluates n/2 which, since both n and 2 are integers, is such an integer division. As mentioned before, this result is an integer.

This integer is then passed as argument to floor. But floor expects a floating point variable (or, as Fortran calls it: REAL). Hence the error message:

"[The] argument of floor ... must be REAL."

So, the easiest way to get what you want is to just remove the floor altogether, since the integer division does exactly what you want:

q = n/2 ! Integer Division

If you need to make a floating point division, that is if you want two integer variables to divide into a real variable, you have to convert at least one of them to floating point before the division:

print *, 3/2           ! wrong, prints 1
print *, real(3)/2     ! right
print *, 3/2.0         ! right
print *, (3 * 1.0) / 2 ! right
print *, real(3/2)     ! wrong, prints 1.0
chw21
  • 7,970
  • 1
  • 16
  • 31