Re: Interpretation of literal reals



N. Shamsundar <shamsundar_at_@xxxxxx> wrote:

> According to the rules of Fortran (77, 90, 95, 2000) a real constant 
> with no decimal point, with or without an exponent field, is treated 
> differently in program source than during formatted input.

I can't make any sense out of that sentence. In particular, there is no
such thing as "a real constant with no decimal point". There certainly
is no such thing "in program source". A string of digits with no decimal
point in program source would be an integer rather than a real constant.
In your example

   x=123

the 123 is *NOT*, let me repeat that *NOT* a real constant. If you think
of such things as real constants, you will go down a road to many
errors. It is an integer constant. The assignment statement causes the
integer value to be converted to a real before it is assigned to x, but
that is not at all the same thing as saying that the 123 is a real
constant in the first place. Yes, it makes a difference. For a trivial
example,

  x = 2/3

will give you a value of zero for x. That is because the 2 and 3 are
integers, so the division is the integer division operation. The
conversion to real does not happen until later, when the resulting value
is assigned to x.

As for I/O, I think old versions of the standard might have misused the
term "constant" to refer to formatted I/O fields, but formatted I/O
fields really do not contain constants; they are just strings of
characters that get converted during I/O. The syntax has similarities to
that of a constant, but it is not the same thing and should not be
confused.

Although I can't figure out what the above says, I can make more sense
of the example code.

> List directed input works as a user would expect. As the ISO-F95 
> standard says in Sec. 10.9.1 (emphasis added),
  [elided]
Ok.

Do note, however, that in f77 this does *NOT* apply to internal I/O, as
used in your example. List-directed formatting is not allowed for
internal files in standard f77, and there used to be f77 compilers that
didn't do it. I believe that relatively recent f77 compilers tend to
support it as an extension, but older ones didn't.  (Heck, most recent
f77 compilers are f90/f95 compilers).

This probably doesn't directly relate to your question, but as long as I
am in pendant mode, I'll note it.

> whereas, for F editing with no decimal point in the input field, Sec.
> 10.6.1.2.1 says:
  [elided]

> Comments, please?

Well, my first comment is that one should generally put the decimal
point in. I realize, however, that there are cases where that isn't
going to happen. For example, if a user interactively types in a value
without a decimal point, the program ought to be able to deal with it
rather than give strange results.

As far as I can tell, the complaint is that both the "10" and the ".5"
part of e10.5 and f10.5 actually mean something. I'm puzzled about why
you are puzzled about this. Yes, they mean something, as you have
quoted. Your biggest complaint appears to be about the ".5".
List-directed input is more like a ".0". If that is what the people in
question wanted, then they should have used a ".0". I just don't
understand why they would put a ".5" and expect it to be ignored and act
like a ".0".

I agree that the ".5" does "strange" things on input. In my opinion, it
is a throwback to some of the worst aspects of the punch-card days,
where the decimal point might have beeen omitted to save a precious
column. My rule is to *NEVER* use anything other than ".0" for real
input formats if there is any possibility that the input data might have
an omitted decimal point, even by accident. That includes any case where
the input data might be manually prepared. In cases where the input data
is always generated by a formatted write, I might relent and allow the
same format to be used for reading, even though it has something other
than ".0".

But I am very mystified as to why this could be a porting issue, as I
have trouble imagining any compiler that would not have correctly
treated the ".5", where "correctly" here means the way that you seem to
not expect. I *DO* know of a vaguely related porting issue, which can be
a problem even when using the ".0" as I recommend. I am more than a
little suspicious that this other issue is your real problem and that
you just haven't identified it. It is an issue I ran into long ago.

The issue is an artifact of f66 and earlier, but its effects linger on
into f77. It involves the treatment of blanks in formatted input.

In f66, blanks in numeric fields acted like zeros. Thus, if you had a
field width of 10, with contents of "123       ", this was effectively
the same thing as "1230000000", which I agree I sure find strange. This
makes no difference when you have an explicit decimal point, because,
for example, "123.000000" has the same value as without the trailing
zeros.

F77 mostly fixed this oddity (in my opinion) of blank treatment. By
default, blanks are treated as blanks. Thus all works "sensibly" (as
long as you use ".0" in your edit descriptors; if you use something like
".5", you are still going to get nonsense just as it explicitly asks for
- don't do that). The new f77 OPEN statement allowed you to specify the
old f66 behavior if you neede compatibility with it.

However, the caveat that I ran into about 20 years ago, and I guess
perhaps the one that is hitting you now... the f77 standard specified
this "new" behavior only via the OPEN statement. For files accessed
without using an OPEN statement, the standard was silent about whether
to apply the new or old behavior. I didn't at first notice this because
the standard didn't actually say that it was processor-dependent. The
standard just specified what happened in an OPEN statement and was
otherwise silent.

Internal I/O does not involve an OPEN statement.

Some compilers did the "sensible" thing and made internal I/O act just
like an opened file in this regard. Other compilers did the other
sensible thing and made internal I/O act just like f66 I/O on this.  :-(

The f90 standard "laid down the law" (figuratively) and specified that
internal I/O has to treat blanks as blanks (instead of as zeros) by
default in internal I/O. So all f90 compilers should be the same in this
regard (though some might have switches for compatibility with old
compiler-dependent codes). But f77 compilers are not all the same.

Therefore, if your code might ever need to run on a pre-f90 compiler,
and you do internal reads of real data that might omit the decimal
point, you have to make your requirements for blank treatment explicit
instead of just using the compiler default. You make your requirements
explicit by using the bn or bz edit descriptors. BN stands for
blanks-null (that is, a blank is sort of like nothing being there). BZ
stands for blanks-zero (a blank is like a zero being there).

So you probably want a format something like "(bn,f10.0)". That will
interpret "123       " as just "123", giving you the real value 123.0.
You "shouldn't" need to do this for f90 becasue it is what the standard
specifies. If you wanted the old f66-ish behavior (ignoring the fact
that f66 didn't have internal I/O), you'd use "(bz,f10.0)", though I
regard that last one as an abomination, and it doesn't sound like what
you want either.

So yes, f77 had several portability issues in the area of internal I/O.
List-directed internal I/O was nonstandard (and not universally
supported). And the default blank treatment for internal IO was
compiler-dependent.

-- 
Richard Maine                     | Good judgment comes from experience;
email: my first.last at org.domain| experience comes from bad judgment.
org: nasa, domain: gov            |       -- Mark Twain
.