- THE PL/I NEWSLETTER - |
| - THE PL/I NEWSLETTER - |
- THE PL/I NEWSLETTER - |
The first issue may be downloaded from:
The PL/I Newsletter, No. 1, July 2000.
The second issue may be downloaded from:
The PL/I Newsletter, No. 2, September 2000.
The third issue may be downloaded from:
The PL/I Newsletter, No. 3, June 2001.
The fourth issue may be downloaded from:
The PL/I Newsletter, No. 4, September 2001.
If a plain list of values is supplied as the command-line arguments,
e.g., 16, 71, -14 or 15 163 924
then GET LIST may be used:
Recent discussion about the decimal division drew attention to
using it.
Extra care is needed when using fixed-point arithmetic including
FIXED DECMAL and FIXED BINARY.
In general, PL/I attempts to accommodate all digits of the result,
whether the operation be addition, subtraction, multiplication,
or division.
Consider the addition of A and B, where A and B are defined in
DECLARE (A, B) FIXED (4,2);
The precision of A + B is (5,2), which accommodates all
possible results without overflowing, including the addition of
such values as 99.99 and 99.99, which gives 199.98
Multiplication of A and B produces a result of precision
(9,4) [A and B are assumed to be defined as above]
which acommodates the product of the smallest values 0.01 and 0.01,
giving 0.0001
It also accommodates the product A*B of the largest possible values
99.99 and 99.99, giving 9998.0001
Division is another kettle of fish.
Division always produces a result having the maximum number of
digits permitted by the installation.
The number of digits after the decimal point depends on the precisions
of the operands.
Bear in mind that PL/I will attempt to produce the greatest number of
digits after the decimal point, consistent with the aim of producing
an accurate and sensible result when the largest number is divided by
unity.
For the result, the number of digits before the point depends on the
number of digits before the point in the dividend.
The result can overflow when the largest value is divided
by a value smaller than unity.
Consider DECLARE (A, B) FIXED DECIMAL (5, 2);
The precision of A/B is (15,10).
If, however, the declarations are changed to:
DECLARE (A, B) FIXED DECIMAL (15, 8);
Then the precision of A/B is (15, 0) -- that is, an integer.
There are no fraction digits.
This outcome is governed by the maximum number of digits
permitted by the installation, namely 15.
If the maximum number of digits permitted is raised to 31,
an entirely different precision is obtained.
A/B then yields a result of precision (31, 16), which is a
consistent with that obtained above when A and B are defined
with precision (5,2).
This "phenomenon" occurs when the number of digits in the dividend
exceeds half the maximum permitted.
No doubt the maximum number of digits (15) in the early S/360
implementations was influenced by hardware considerations.
However, with the VisualAge PL/I compiler it is possible to specify
the maximum number of digits as 31. The Kednos compiler (Compaq)
already has this limit.
The VisualAge PL/I compiler option is LIMITS (FIXEDDEC(31)), specified
on the PROCESS statement thus:
%PROCESS LIMITS (FIXEDDEC(31));
Just for the record, the precision of the result of division is
(M, q),
where q = M - p1 + q1 - q2.
M = maximum number of digits permitted;
The precision of the dividend is (p1, q1),
The precision of the divisor is (p2, q2).
Observation
If decimal division is required in a simple statement,
D = A/B may be adequate, provided that p1 < M/2.
If the division is only part of the operations of an expression,
it would be better to use the DIVIDE built-in function to ensure
that fraction digits are not lost.
In any case, when execution time is important, DIVIDE should be used
to avoid generating unnecessary result digits.
DIVIDE can also be used to accommodate the division of the
largest possible value of dividend by the smallest possible value
of divisor.
Similar considerations apply when the operands are FIXED BINARY, when scaled results are permitted.
Conclusion
When division is used in an expression, it would be advisable
to use the DIVIDE built-in function to produce a result having
a precision consistent with the other components in the expression.
In particular, specify the number of digits after the decimal/binary
point desired by the user.
In issue No. 3 of The PL/I Newsletter, we looked at some of the (new) built-in functions of IBM VisualAge PL/I. Here we discuss some more of them.
The spring 2000 edition of the
COBOL and PL/I newsletter
has some topics about PL/I. The specific PL/I
topics may be viewed separately, or the entire newsletter in PDF
format may be downloaded.
Of particular interest is the use of PL/I as a programming
language for the Common Gateway Interface (CGI).
The PL/I Connection newsletter.
The PL/I Connection Newsletter No. 11 , December 1997.
The PL/I Connection Newsletter No. 10 , April 1997.
VisualAge PL/I Enterprise Edition Version 2.1 combines the two separate offerings from the previous release of VisualAge PL/I (Standard and Professional) into a single offering available on both the OS/2 and Windows NT platforms. By doing so, it provides these productivity features:
Also included as an extra bonus offering is VisualAge CICS® Enterprise Application Development, which enables CICS host application development on the workstation.
An HTML version of "The Multics PL/1 Compiler" by Bob Freiburghouse from the 1969 FJCC has been added to the Multics website at http://www.multicians.org/pl1-raf.html with Bob's permission.
This paper describes the Multics version 1 PL/I compiler's implementation.
Built-in functions are generic, and typically operate on any data type and
for an array of any number of dimensions (up to the maximum permitted
by the compiler).
If a user attempts to write a generic function, it is necessary to
provide the procedures to perform the desired operation on each of the
data types that he wants.
As well, if the argument(s) can be arrays, the user must also provide
procedures to perform the desired operation on arrays of any number
of dimensions. Each procedure dealing with an array must also be
duplicated to deal with each of the different types that the user wants.
Thus, if there are four data types (integer, decimal, float, float (16)),
and the compiler supports arrays having 10 dimensions, then 40 procedures
must be provided.
It would be better to have a new attribute GENERIC_ALL
which specifies that any procedure
in the family is assumed to apply to scalars and arrays of any
dimension. e.g.,
To improve debugging, incorporate the following in your procedures.
This month's problem
Whereas the previous problem presented a situation which you hopefully never will experience, the new problem asks for a solution you probably have wanted sometimes. In the following code fragment you have to replace the ellipses by some statements in order to being able to use array constants:
Please send your solutions to Eberhard Sturm at: sturm@UNI-MUENSTER.DE