[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

floating-point format



I went and read the Fortran-77 standard, so now I understand Guy's
proposal.

This mess consists of several sections, separated by rows of dashes:
Guy's proposal (from the memorial day ballot); a condensed form of
the Fortran FORMAT-statement documentation; my suggestions; and the
documentation for ~$ as its exists now in the Lisp machine (Scribe
commands and all).
----------------
16. Guy proposes the following treatment of floating point in FORMAT:

	~w,d,pF
	~w,d,x,pE
	~w,d,pG

The meanings of the arguments are exactly as for the FORTRAN-77
language as described in chapter 13 of the FORTRAN-77 standard,
with the following exceptions and extensions:

(a) The scale factor p is an explicit parameter, rather than being
established be a separate preceding directive.  For ~F, p defaults to 0,
and for ~E and ~G it defaults to 1.  (In FORTRAN p always defaults
to 0.)

(b) If w is omitted, then the output is variable-width, and never
produces a field of asterisks; the other parameters are observed,
however.  So "~,2F" will always print exactly two digits after the
decimal point, and prints as many as necessary to the left of
the decimal point.

(c) If d is omitted then as many digits are produced as necessary
to preserve the information content of the number, except that if
w is specified then the width constraint it imposes overrides this
consideration.  (Thus if both are omitted we get free-format output.)

(d) The format operation formerly called ~G will henceforth be called ~@*.

----------------
 From ANSI X3.9 1978  (selected highlights from chapter 13)

SP requires + to be output.  SS forbids + to be output.  S
restores the default, which gives the processor the option
of outputting or not outputting + in I, F, E, D, and G editing.

With a scale factor p: On output, with E editing, the basic real
constant part of the quantity is multiplied by (expt 10 p) and the
exponent is reduced by p.  On F output editing the scale factor effect
is that the externally represented number equals the internally
represented number multiplied by (expt 10 p).  On output, with G
editing, the effect of the scale factor is suspended unless the use of E
editing is required.

The processor must not produce a negative signed zero in a
formatted output record.

On output the representation is right-justified in the field.

On output, if the number of characters produced exceeds the field width
or if an exponent exceeds its specified length, the processor will fill
the entire field with asterisks.  However the processor must not produce
asterisks if the field width is not exceeded when optional characters
are omitted.  Plus sign is not optional when SP is in effect.

F editing: Optional blanks, optional sign, and a string of digits that
contains a decimal point, rounded to d fractional digits.  Leading zeros
are not permitted except for an optional zero immediately to the left of
the decimal point if the magnitude is less than one.  The optional zero
must appear if there would otherwise be no digits in the output field.
[It says nothing about trailing zeros.]

E editing: ~w,d,x,pE
The form of the output field for a scale factor p of zero is

	optional-sign optional-zero decimal-point d-digits exp

where exp is a decimal exponent of one of the following forms:

x unspecified, (abs exponent) <= 99: E plus/minus digit digit
				  or plus/minus zero digit digit

x unspecified, (< 99 (abs exponent) 1000): plus/minus digit digit digit

x specified, (< (abs exponent) (1- (expt 10 x))): E plus/minus x-digits

The sign in the exponent is required.  A plus sign must be used if
the exponent value is zero.  x must not be unspecified if the
absolute value of the exponent exceeds 999.

If -d < p <= 0, the output field contains exactly -p leading zeros
and d-(-p) significant digits after the decimal point.  If 0<p<d+2,
the output field contains exactly p significant digits to the left
of the decimal point and d-p+1 significant digits to the right of
the decimal point.  Other values of p are not permitted.

G editing: ~w,d,x,pG
The method of output depends on the magnitude of the datum:
< 0.1:			use E format with same parameters
>= (expt 10 d):		use E format with same parameters
>= (expt 10 (1- a))
 and < (expt 10 a):	~(w-n),(d-a)F ~n@T

where n = x+2 or 4 if x is unspecified
and (<= 0 a d).  Thus if F format is used, d significant digits are
printed, of which d-a are fractional, and the overall field width is the
same, with some spaces on the right.

----------------
I like all four exceptions/extensions in Guy's proposal.

On signs: The @ modifier forces a plus sign to be printed, as in ~D.
Without an @, a plus sign is never printed.  In either case a minus sign
is printed if the number is negative.  Fortran's prohibition against
negative zero is overruled by the proposed IEEE standard.

On arguments: ~F should not allow a scale factor, since it actually changes
the magnitude of the represented number.  (I am amenable to allowing it
anyway, since it's optional and the last argument, if anyone has a use
for it).  ~w,d,x,pG  (note the added x) because it has to pass this on
to ~E if the number is large or small, and if the number is intermediate
it has to use x to line up the columns.

On exponent markers: should the exponent marker always be E?  Always
be the same type-dependent exponent marker that PRINT would use?
Or should the : modifier switch between always using E as the exponent
marker and using the type-dependent exponent markers that PRINT uses?

On optional characters: the exponent marker should never be optional.
The sign and leading zeros in the exponent should not be required.
But there is an issue here of trying to line things up in columns.
How about if x is specified then the exponent occupies exactly
x+2 columns, consisting of the E (or other marker), a required sign,
and x digits with leading zeros, whereas if x is unspecified then the
exponent consists of an E (or other marker) followed by a free-format
integer.

On trailing zeros: if d is specified, trailing zeros are printed.  If
d is unspecified, trailing zeros are suppressed, except that at least
one digit is printed to the right of the decimal point.

On field overflow: we aren't dealing with 80-column cards here, and
I don't think asterisk fill is ever appropriate.  I'd rather see
Common Lisp specify either:
    (1) If a number doesn't fit in a field then it is printed in
	as wide a field as required to represent it.  If a number
	printed in F format is too large, E format may be used.
 or (2) If a number doesn't fit in a field then the results are
	whatever the implementation finds easiest or most tasteful.

On G format: the essential features of G format as compared with F
format are that small numbers are represented exponentially, rather
than underflowing to zero, and that when no exponent is printed blank
space is left where the exponent would be so that the numbers line up
(I suggest we do this only if x is specified).

On type errors: if any of these format operators see a rational
number, they float it and proceed.  If any of these format operators
see a non-number, they output it in ~wA format, with *BASE* decimal.
I don't know what is best for complex numbers here.

----------------
The following is the documentation for ~$ as it currently exists.

@subsection(~$ @L[format] directive for floating point)
@L[~$] is a previously undocumented @L[format] directive for floating
point values.
@IndexEntry[Entry={~$},Key={$},Number]
@Index[~$]
@Index[floating point values]
@IndexEntry[Entry/{@L[format] directive},Key/{format directive},Number]

The format for using it follows:
@display{@L[~@i[rdig],@i[ldig],@i[field],@i[padchar]$]}
It expects a flonum argument.  The modifiers for @L[~$] are all
optional. 
@begin(desplay)
@I[rdig]@\The number of digits after the decimal point.  The
default is 2.

@I[ldig]@\The minimum number of digits before the decimal point.  The
default is 1.  It pads on the left with leading zeros.

@I[field]@\The full width of the field to print in.  The default is the
number of characters in the output.  The field is padded
to the left with @I[padchar] if necessary.

@I[padchar]@\The character for padding the field if the field is wider
than the number.  The default is @L[#\space].

@i[:]@\The sign character is to be at the
beginning of the field, before the padding, rather than just to the left
of the number.

@i[@@]@\The number must always appear signed.
@end(desplay)
@verbatim[@OK[]@~
(format t "~&Pi is ~$" (atan 0 -1))  =>
Pi is 3.14
(format t "~&Pi is ~8$" (atan 0 -1))  =>
Pi is 3.14159265
(format t "~&Pi is ~8,2@@:$" (atan 0 -1))  =>
Pi is +03.14159265
(format t "~&Pi is ~8,2,20$" (atan 0 -1))  =>
Pi is          03.14159265
(format t "~&Pi is ~8,,20,'x@@$" (atan 0 -1))  =>
Pi is xxxxxxxxx+3.14159265
]

It uses free format (@L[~@@A]) for very large values of the argument.
@Index[@L{~@@A}]