[comp.lang.fortran] problem with "pe" format

GL4@psuvm.psu.edu (06/04/90)

(I hope this isn't a repost -- I think I screwed up the first time)

A user brought the following program to my attention, and I am unable to
explain the output:

---------------------------------------------
       x=1.11
       fs=10.0
       write(*,32) x,fs
32     format(1pe13.3,f10.1)
       write(*,*) fs
       end
---------------------------------------------
output:
       1.111E+00     100.0
      10.00000
---------------------------------------------

 Does anyone know why the value of "fs" is multiplied by a factor of
 ten? I've tried this on a Sun-3, a Gould 9005 running UTX/32 2.1A,
 and an IBM mainframe, and gotten the same results.

 If I change the number in front of "pe" to a 2, "fs" is multiplied
 by a factor of 10**2, and so on.

 Any clarification would be greatly appeciated (even of the type, "This
 is standard Fortran behaviour, you lamebrain. RFTM").

 Garth Longdon.

 gl4@psuvm.bitnet
 longdon@itd.nrl.navy.mil

calvin@dinkum.sgi.com (Calvin H. Vu) (06/05/90)

In article <90155.122858GL4@psuvm.psu.edu> GL4@psuvm.psu.edu writes:

>---------------------------------------------
>       x=1.11
>       fs=10.0
>       write(*,32) x,fs
>32     format(1pe13.3,f10.1)
>       write(*,*) fs
>       end
>---------------------------------------------
>output:
>       1.111E+00     100.0
>      10.00000
>---------------------------------------------

> Does anyone know why the value of "fs" is multiplied by a factor of
> ten? I've tried this on a Sun-3, a Gould 9005 running UTX/32 2.1A,
> and an IBM mainframe, and gotten the same results.

The P Editing causes every real number following it (until another P 
editing if any) to be multiplied by 10**k where k is called the scale
factor and is the number in front of the P.  A less confusing way to
write this is:
32     format(1p,e13.3,f10.1)

Without the scale factor specified, i.e. if the format had been:
32     format(e13.3,f10.1)

the result would have been:
    0.111E+01      10.0
    10.00000    

If you note the difference between the two results you can figure out the
effects of the P edit descriptor.
I'm a little lazy to type all the details so maybe you do need to RTFM :-).
--------------------------------------------------------------------------
Calvin H. Vu			   | "We are each of us angels with
Silicon Graphics Computer Systems  | only one wing.  And we can only
calvin@sgi.com   (415) 962-3679	   | fly embracing each other."

ok@goanna.cs.rmit.oz.au (Richard A. O'Keefe) (06/05/90)

In article <90155.122858GL4@psuvm.psu.edu>, GL4@psuvm.psu.edu writes:
*        x=1.11
*        fs=10.0
*        write(*,32) x,fs
* 32     format(1pe13.3,f10.1)
* ---------------------------------------------
*        1.111E+00     100.0
	 ^^^^^ I hope this was really 1.11

"p" isn't a modifier on a single format, but a formatting command
in its own right, whose effect persists within the same format until
you explicitly reset it.  Blank and sign handling are similar.
That's the way it's supposed to be.

-- 
"A 7th class of programs, correct in every way, is believed to exist by a
few computer scientists.  However, no example could be found to include here."

maine@elxsi.dfrf.nasa.gov (Richard Maine) (06/05/90)

On 4 Jun 90 16:28:58 GMT, GL4@psuvm.psu.edu (Garth Longdon) said:

Garth> A user brought the following program to my attention, and I am
Garth> unable to explain the output:
Garth>  ...
Garth> 32    format(1pe13.3,f10.1)
Garth>  ...
Garth> ...[questions about the effects of the P scale factor in formats]..

Garth>  Any clarification would be greatly appeciated (even of the type, "This
Garth>  is standard Fortran behaviour, you lamebrain. RFTM").

Ok, I'll go with "This is standard Fortran behavior", but I can't agree with
the "lamebrain" part.  Though it is standard, it is certainly subtle and
confusing.  I've had quite competent programmers come to me after spending
many hours trying to "debug" programs whose only problem was in the output
format statement.  (They were trying to figure out how the values got to be
a factor of 10 off, not realizing that this was an artifact of the format).
And I'll try to elaborate a little on the FM.

You are seeing the combined effects of two confusing "features".  The first
feature, as pointed out by some other follow-ups, is that the P scale factor
continues its effect throughout the format statement, even though it is
placed next to the e13.3 in a manner that "looks like" it applies only to
the e13.3 part.  To make the !p apply only to the e13.3, you could do
something like
        format(1p,e13.3,0p,f10.1)

The second feature is the strange effect of the P scale factor on F format
descriptors.  I'd explain the effect by saying that the P scale factor does
the same thing to the mantissa of E and F format items; it multiplies them by
the appropriate power of ten.  On E formats, it then compensates by lowering
the exponent value.  On F formats, there is no exponent, so the number is
just left off by some factor of 10.  I think this behavior is "wrong".  I
have never seen anywhere that such behavior was desirable, and I've seen
plenty of users confused by it.  Sure, you could invent some situation where
this feature could be used, but I'm dubious that those rare cases justify
the confusions caused elsewhere.  Regardless of my opinions about this
feature, it is standard.  Oh yes, if I recall, the effects on input are
equally confusing.

While I'm on the subject of P scale factors, let me point out another
"feature" that I think is a bug in the standard (but a bug that all the
compiler vendors seem to strictly follow). I mentioned this bug in my
official comments on the Fortran 90 standard, though I didn't really
expect the ANSI committee to make any changes based on my comment, this
bug having by now achieved the status of standard practice.

If you use the P scale factor with G format descriptors, it does strange
things to the number of significant digits for no ascertainable reason.
For instance, without a scale factor, the format descriptor G10.4 always
gives 4 significant digits.  This is the most significance you can get
in a 10-character field with E or G (or D) formats for arbitrary values
(well, anyway if the exponent is limitted between -99 and +99).  It happens
that this precision is just barely adequate for some of my applications.

You would not think (anyway, I wouldn't) that the scale factor would have
anything to do with the number of significant digits.  Indeed 1PG10.4
still has 4 significant digits when the value is in the range that gives
an "F type" output.  However, for large or small values such that an
"E type" output results, 1PG10.4 gives 5 significant digits (and thus
does not fit in the field of 10 for negative values).  The same 5 significant
digits result for all P values except 0; that is, 2PG10.4 and 3PG10.4 also
give 5 significant digits (should anyone ever want them, negative scale
values still give 5 digits, though some of them are leading 0's and thus
not technically "significant" by most definitions).

Thus, if you want to use a scale factor with G format decsriptors, the
most significance you can fit in a field of 10 is with 1PG10.3.  This
gives 4 significant digits in the E form, but only 3 in the F form.
The 3 significant digits are insufficient for me, so I avoid using
scale factors with G format, much as I generally prefer !p to the
default 0P.

I have never been able to figure out the rationale for this behavior.  My
best guess is that it is simply a "typo" in the standard and not what was
intended.  Perhaps one of the committee members that frequent this group
can correct this guess.  Regardless of the intent, it IS in the standard,
and compilers DO implement it.


--

Richard Maine
maine@elxsi.dfrf.nasa.gov [130.134.64.6]

GL4@psuvm.psu.edu (06/07/90)

Thanks to everyone who e-mailed me about the problem I was having with the
"p" format specifier. As everyone noted, this really *is* standard (although
very strange) FORTRAN behavior.

I'd be curious to know if anyone can think of a sitution where you'd actually
*want* the magnitude of the output to be changed like that.


Garth Longdon.

jeffe@eniac.seas.upenn.edu (George J. Jefferson) (06/07/90)

>I'd be curious to know if anyone can think of a sitution where you'd actually
>*want* the magnitude of the output to be changed like that

when writing labels for a plot axis you can 'scale' all of the values
and then indicate the 'scale factor' just once

However, uses like this are so rare that the programer could just as
well do it 'by hand'

George Jefferson    jeffe@eniac.seas.upenn.edu   george@sol1.lrsm.upenn.edu

buckland@cheddar.ucs.ubc.ca (Tony Buckland) (06/08/90)

In article <90158.091706GL4@psuvm.psu.edu> GL4@psuvm.psu.edu writes:
>
>Thanks to everyone who e-mailed me about the problem I was having with the
>"p" format specifier. As everyone noted, this really *is* standard (although
>very strange) FORTRAN behavior.
>
>I'd be curious to know if anyone can think of a sitution where you'd actually
>*want* the magnitude of the output to be changed like that.

 One use is in scaled currency applications, where you have internal
 cents or centicents and want to print dollars or cents without
 the bother of dividing everything by a hundred first.  I could
 see extending this to scientific calculations where nanometers
 are printed as Angstrom units, etc.  Returning to the currency case,
 you can see the advantage of being able to print an entire
 financial report with hundreds of variables, scaling everything
 with just one itty-bitty "P" at the beginning of the FORMAT.

jlg@lambda.UUCP (Jim Giles) (06/08/90)

From article <90158.091706GL4@psuvm.psu.edu>, by GL4@psuvm.psu.edu:
> [...]
> I'd be curious to know if anyone can think of a sitution where you'd actually
> *want* the magnitude of the output to be changed like that.

Consider a code in which you know that a given value is stored internally
in meters.  With the Fortran rules, you can write:

      Write(*,'('' Distance is '',6pf10.6,'' microns'')') x

Later, you can just change the format to get:

      write(*,'('' Distance is '',3pf10.6,'' millimeters'')') x

Admittedly, this is not a really particularly useful or common feature.
I would also prefer that P not effect F formats and P should only effect
one format specifier not all until the next P.  However, such a change is
unlikely because of backward compatibility.

J. Giles

seymour@milton.acs.washington.edu (Richard Seymour) (06/08/90)

there's also the case of using Exponent notation (E-format).
in standard fortran (ansi x3.9-1978 page 13-11) the ONLY way to
get other than a single zero to appear to the left of the decimal
point is via the P scale factor.
   E12.3   gives   0.270e+02  as output
 1PE12.3    gives  2.701e+01  as output
 2PE12.3    gives  27.012e+00   as output
(i believe) there is NO other way (without building strings of integers)
to get other than a single zero before that decimal point.
(the same argument applies if you want leading zeroes to the RIGHT of
the decimal point:    -1PE12.3 gives 0.027e+04  )
--dick

ok@goanna.cs.rmit.oz.au (Richard A. O'Keefe) (06/08/90)

In article <8159@ubc-cs.UUCP>, buckland@cheddar.ucs.ubc.ca (Tony Buckland) writes:
> In article <90158.091706GL4@psuvm.psu.edu> GL4@psuvm.psu.edu writes:
> >Thanks to everyone who e-mailed me about the problem I was having with the
> >"p" format specifier. As everyone noted, this really *is* standard (although
> >very strange) FORTRAN behavior.

> >I'd be curious to know if anyone can think of a sitution where you'd actually
> >*want* the magnitude of the output to be changed like that.

Several people have suggested why you would want P at all, though no-one
as yet has pointed out that decimal scaling can be done by the formatting
routines without _any_ extra roundoff error.

As to why you would want it to be sticky, consider two facts:
(a) you want pe, pf, pg, so it looks as though it might be simpler
    for the "p" part to be a separate formatting command
(b) but you also want p10e and the like, and it's simplest to
    explain (and implement!) if p just sets a global variable.

Another possibility would have been for everything that uses the 'p'
flag to reset it to its default value, but then you'd have to write
	10(p,e)
rather than p,10e and unfortunately that might not interact with
Fortran's rules about the last set of parens in a format just the way
you would want.

So my surmise is that the expectation was that if you wanted scaling
you were probably printing out a table and wanted everything scaled
the same way, and that if you didn't want everything scaled the same
way it would be clearer if everything in the format had its own scale.

A rule of thumb for keeping things straight, then, is that if you
use P in a format at all, you should

	either put P first in the format (so you _know_ when it is
	set and that it applies to everything)

	or give each relevant item its own P	
-- 
"A 7th class of programs, correct in every way, is believed to exist by a
few computer scientists.  However, no example could be found to include here."