program testdp
implicit none
integer, parameter::dp=selected_real_kind(14)
real(dp),parameter::a=1_dp,b=2_dp,c=a/b,d=1_dp/2_dp
write(*,*)c,d
end program testdp
Because a real literal constant must contain at least one of: a
decimal point or an exponent part (MR&C, p. 15). Yours contain
neither. Your constants are integers.
Regards,
Mike Metcalf
1_dp and 2_dp are still integers, even if they have
the KIND of dp.
You would have a compile time error if no appropriate
INTEGER KIND existed.
It might have been nice if it was reqiured for KINDs not
to overlap between different types.
-- glen
Both comments make perfect sense. I did a search and replace in a
larger code for items like 4d0 changing it to 4_dp, but forgot I needed
to add either an exponent or a decimal point. Trying to clean up old
code and got bit. Thanks to both of you for your answers.
Yes. I personally think it would have been nicer still if kinds weren't
numeric. F90 introduced features that programmers can use to get away
from darn near everything being integer codes, but the language itself
doesn't take good advantage of those features. I sometimes think that at
least some of the people writing the language specs weren't yet
themselves fuly comfortable with some of the newer features. (Other
times I am sure of it instead of just thinking so. :-)).
Anyway, spilt milk aside, the thing to understand is that dp above is
just an integer parameter. Odds are that it is 8, though that will vary.
In any case, it is a named parameter for some integer value. That is
*ALL* it is. The fact that its value was computed using
selected_real_kind does *NOT* restrict it to being used as a real kind
parameter. That's the most obviously useful way to use it, but you can
use it anywhere else that you could use an integer parameter with the
value 8 (or whatever).
Unfortunately, one of those other places that you can use a parameter
with the value 8 is as a kind specifier for integer. Odds are that 1_dp
and 2_dp are 8-byte integers. The reason I say it is unfortunate is that
it invites exactly the kind of error that the OP had here. The code
shown is perfectly valid; it is just highly unlikely that it does what
the writer intended.
--
Richard Maine | Good judgment comes from experience;
email: last name at domain . net | experience comes from bad judgment.
domain: summertriangle | -- Mark Twain
Because you have 1/2, which is integer division.
To make it real division, you must have something like
1.0_dp/2.0_dp.
But why not just write 0.5_dp? No monkey business there !
Note also that "a = 1_dp" is not what you think it is.
Again, here, the 1_dp is an INTEGER constant, not a REAL constant.
> | real(dp),parameter::a=1_dp,b=2_dp,c=a/b,d=1_dp/2_dp
Well, a is a PARAMETER and, as the declaration says, is REAL,
with KIND(DP).
-- glen
>
>Anyway, spilt milk aside, the thing to understand is that dp above is
>just an integer parameter. Odds are that it is 8, though that will vary.
>In any case, it is a named parameter for some integer value. That is
>*ALL* it is. The fact that its value was computed using
>selected_real_kind does *NOT* restrict it to being used as a real kind
>parameter. That's the most obviously useful way to use it, but you can
>use it anywhere else that you could use an integer parameter with the
>value 8 (or whatever).
>
I find this part terribly confusing. Not your answer per se, but the part about reals and integers.
If a parameter is declared as real, shouldn't it be considered as such even with the
dot missing ?
Kind only takes care of a range and precision (mantissa+exponent).
I can't think of a case where this would be useful, instead of just producing hard to spot errors
(like the one op exerciced).
pp, Luka
>>Anyway, spilt milk aside, the thing to understand is that dp above is
>>just an integer parameter. Odds are that it is 8, though that will vary.
>>In any case, it is a named parameter for some integer value. That is
>>*ALL* it is. The fact that its value was computed using
>>selected_real_kind does *NOT* restrict it to being used as a real kind
>>parameter. That's the most obviously useful way to use it, but you can
>>use it anywhere else that you could use an integer parameter with the
>>value 8 (or whatever).
> I find this part terribly confusing. Not your answer per se,
> but the part about reals and integers.
> If a parameter is declared as real, shouldn't it be considered
> as such even with the dot missing ?
Yes, a PARAMETER declared REAL has type REAL, even with the dot missing.
The usual rules for expressions evaluation still apply, though,
in determining the value.
REAL A
A=5/2
gives A the REAL value 2.0, after converting the INTEGER 2
to REAL. Similarly,
REAL, PARAMETER:: B=5/2
gives B the REAL value 2.0
> Kind only takes care of a range and precision (mantissa+exponent).
> I can't think of a case where this would be useful, instead
> of just producing hard to spot errors (like the one op exerciced).
It would be standard conforming to have a disjoint set if KINDs
between INTEGER kinds and REAL kinds. That would allow the compiler
to catch this error. It seems that many compilers use the size
in bytes for the KIND values, except for COMPLEX types.
-- glen
But that does not make sense, though I too was confused by the
d=1_dp / 2_dp
I have learned that the types of operands on the right are not promoted to
(or related to) the type of the variable on the left. Instead, 1/2 is
truncated to 0 and assigned to d.
Suppose for the sake of argument that we want this type of error to be
detected. dp is of type integer. Any other integer that evaluates to a valid
kind for an integer could be mis-used in the same way without producing an
error.
Yet "dp" is not bound in any way to type "real". There is no type in Fortran
such as "kind_specifier_of_real". Perhaps there should be, but now it's
probably too late as that would break existing code unless some *new*
inquiry functions were added to the language that returned enumerators of
the proper "type". (Sorry about that!)
-- e
> On Thu, 11 Mar 2010 14:32:57 -0800, nos...@see.signature (Richard Maine)
wrote:
>
> >
> >Anyway, spilt milk aside, the thing to understand is that dp above is
> >just an integer parameter. Odds are that it is 8, though that will vary.
> >In any case, it is a named parameter for some integer value. That is
> >*ALL* it is. The fact that its value was computed using
> >selected_real_kind does *NOT* restrict it to being used as a real kind
> >parameter. That's the most obviously useful way to use it, but you can
> >use it anywhere else that you could use an integer parameter with the
> >value 8 (or whatever).
> >
>
> I find this part terribly confusing. Not your answer per se, but the part
> about reals and integers. If a parameter is declared as real, shouldn't it
> be considered as such even with the dot missing ?
The parameter is real. What is not real is the expression that is
evaluated to compute the parameter value. That expression in your case
was 1_dp/2_dp, which is an integer expression giving zero. *AFTER* that
expression is evaluated to give 0, it is converted to a real 0.0d0 as
needed for the parameter.
It is *EXTREMELY* important to understand on of the most fundamental
points of Fortran expression evaluation - that evaluation of an
expression does not depend on context. That applies here and to many,
many other situations. That's why the "after" that I emphasized above.
When the compiler is evaluating 1/2 (I'm dropping the _dp parts as just
being distracting here), it does not get to look at how it will be used
in order to define what it means. In Fortran 1/2 evaluates to 0. Always.
No, it is not a real. It is an integer. Only after the expression has
been evaluated to get an integer 0 does the compiler get to look and say
"I need a real here, but that's ok as I know how to convert the result."
Note my phrase "convert the result". It is only the result that gets
converted; the compiler doesn't get to go redefine what everything in
the expression means based on knowing that the result is going to later
get converted.
I also note the aparent confusion of your talking about the parameter
having the dot missing. That confuses different concepts. There is no
dot in a numeric parameter - ever. The 1_dp/2_dp is not the parameter.
Instead, the 1_dp/2_dp is the expression that is evaluated to determine
the parameter value. Do not think of a parameter as being like a macro,
where the actual text is substituted. It is much more like a
compile-time variable. The parameter is (whatever its name was - I don't
have it in front of me) and it has the value of a double precision real
zero.
I apologize if the above seems a bit repetitive. I thought the
repetition is slightly different forms might help get one that "clicks"
for you.
For me, the best part about this episode is a reminder that
initialization expressions are treated no differently than those
evaluated at runtime, and that kind parameters do not in any way specify
the type of the object.
Notice that the compiler can help you:
gfortran -Wconversion test.f90 -o test
test.f90:4.24:
real(dp),parameter::a=1_dp,b=2_dp,c=a/b,d=1_dp/2_dp
1
Warning: Conversion from INTEGER(8) to REAL(8) at (1)
test.f90:4.31:
real(dp),parameter::a=1_dp,b=2_dp,c=a/b,d=1_dp/2_dp
1
Warning: Conversion from INTEGER(8) to REAL(8) at (1)
test.f90:4.44:
real(dp),parameter::a=1_dp,b=2_dp,c=a/b,d=1_dp/2_dp
1
Warning: Conversion from INTEGER(8) to REAL(8) at (1)
Marco
(snip)
That helps, but it would be even better for the compiler to
detect attempts to use a KIND with the wrong type.
It is common, but not required, for the KIND values for INTEGER
and REAL to overlap. If they didn't, compilers would immediately
detect the use of a SELECTED_REAL_KIND value in an INTEGER context.
Presumably this happens rarely enough that there haven't been
complaints to compiler writers.
-- glen
That's irrelevant.
What's relevant is that the constant is an INTEGER.
The constant 1_dp is NOT real. It's an INTEGER.
The parameter is REAL, because it is declared REAL.
You have "declared" the constant to be an INTEGER.
The fact that you have "declared" the constant to be INTEGER
doesn't make it REAL.
The fact that you have assigned an INTEGER constant to a REAL variable
doesn't make the constant REAL. It is still an INTEGER.
An unfortunate choice of values! The constant "2" in the
expression "5/2" is NOT real. It is an integer.
It's the INTEGER-VALUED expression "5/2" that yields 2 exactly,
and it is that which is converted fo REAL for assignment to "A".
There's no need whatsoever for anything like that.
All that is required is for vendors to use different kind numbers
for EVERY kind type.
This is perfectly permissible, since the kind numbers are entirely arbitrary.
Thus, the problem could be solved virtually immediately.
OK. But I don't think the language standards will ever be written at that
level of detail. [smile].
--- e
A gfortran compiler flag I had not discovered. Thanks!
Even if there were, too many program(mer)s assume that kind=8 is double
precision, kind=4 is default integer/default real and that
integer(kind=8) exists. That goes back to the rather common REAL*8
syntax; although kind numbers do not need to be the same, many users
assume they are!
The NAG compiler, which uses by default different kind numbers, has
consequently an option -kind=byte to allow these kind numbers.
Of cause, it would be possible to add such an option to other compilers,
but I doubt that that will ever become the default setting.
* * *
Side remark: gfortran by default does not allow assigning numbers which
overflow but prints (at compile time):
Error: Arithmetic overflow converting REAL(8) to REAL(4) at (1). This
check can be disabled with the option -fno-range-check
However, some people fail to read this error message and even ask in
mailing lists what they should do ...
Tobias
It's an implemntation issue. It doesn't need a directive from
the standard, but it certainly would help.
Any assumption like that makes the code non-portable.