Please, post my message in comp.lang.pl1 - I haven't permission to do it by myself... Sorry to bother you, really..

Quote:

>Hello John,

> I am so sorry to bother you, but don't you mind to send my message

> in comp.lang.pl1? Our network administrator destroys new transport

> on our server, and all of us only can read messages there. Please,

> help me...

> Here is the message:

> Hello, All!

>Maybe you don't believe me, but all what I will tell you is truth. Really.

>So, there is a simple program:

>TSTPL: PROC OPTIONS(MAIN);

> DCL A DEC FIXED (5);

> A=1000+15/3;

> PUT DATA(A);

> END TSTPL;

>I tried to run it in VM/SP 6.18 with PLIOPT version 2.3.0. Here is the compiler message:

>5668-910 IBM OS PL/I OPTIMIZING COMPILER VER 2 REL 3 MOD 0

>5668-910 IBM OS PL/I OPTIMIZING COMPILER TSTPL: PROC OPTIONS(MAIN);

>NO MESSAGES OF SEVERITY W AND ABOVE PRODUCED FOR THIS COMPILATION

>MESSAGES SUPPRESSED BY THE FLAG OPTION: 1 I.

>COMPILE TIME 0.00 MINS SPILL FILE: 0 RECORDS, SIZE 4051

>END OF COMPILATION OF TSTPL

>Here is the assembler listing of the third statement (A=1000+15/3;)

> * STATEMENT NUMBER 30

> 000096 F1 21 D 098 3 050 MVO WKSP.1+32(3),80(2,

> 3)

> 00009C D7 06 D 09A D 09A XC WKSP.1+34(7),WKSP.

> 1+34

> 0000A2 D1 00 D 0A0 3 051 MVN WKSP.1+40(1),81(3)

> 0000A8 FD 80 D 098 3 052 DP WKSP.1+32(9),82(1,

> 3)

> 0000AE D2 07 D 0F0 D 098 MVC 240(8,13),WKSP.1+3

> 2

> 0000B4 F1 32 D 098 3 053 MVO WKSP.1+32(4),83(3,

> 3)

> 0000BA D7 06 D 09B D 09B XC WKSP.1+35(7),WKSP.

> 1+35

> 0000C0 D1 00 D 0A1 3 055 MVN WKSP.1+41(1),85(3)

> 0000C6 FA 97 D 098 D 0F0 AP WKSP.1+32(10),240(

> 8,13)

> 0000CC F8 79 D 09A D 098 ZAP WKSP.1+34(8),WKSP.

> 1+32(10)

> 0000D2 F1 20 D 0B8 D 09A MVO A(3),WKSP.1+34(1)

> 0000D8 D1 00 D 0BA D 0A1 MVN A+2(1),WKSP.1+41

>And here is the result:

>IBM482I 'ONCODE'=0310 'FIXEDOVERFLOW' CONDITION RAISED

> IN STATEMENT 3 AT OFFSET +0000CA IN PROCEDURE WITH ENTRY TSTPL

>The error is in the only one calculating statement. If I write it as

>A=1000+0015/0003;

>everything will be OK.

>I have tested it in older compilers and environments - OS/VS (compiler V1), in VM/ESA 2.2.0

>and so on, but the result was the same.

>How can I solve this problem?

>Best regards,

>Alexander Kostyrko (with great hope)

>p.s. yes, I know, my English isn't perfect, but I am working on it...

This is a classic beginner's mistake.

In the first version, you are dividing a FIXED DECIMAL(2,0) by a FIXED

DECIMAL(1,0).

According to PL/I precision rules, the result of this is FIXED

DECIMAL(15,13). How is

this arrived at? 15 is the maximum precision possible for FIXED DECIMAL

with this particular

compiler. The largest possible quotient of FIXED DECIMAL(2,0) divided by

FIXED DECIMAL(1,0) is 99/1, or 99. So the compiler allows two integer

digits, and allocates

all the rest to the fraction -- 15,13. So your actual result is

05.0000000000000. Then you add

1000 (FIXED DECIMAL(4,0)) to that. The result would be FIXED

DECIMAL(18,13), if that

were possible, but, since it isn't, it tries to fit 01005.0000000000000

into FIXED DECIMAL(15,13),

and fails.

In the second version, you are dividing a FIXED DECIMAL(4,0) by FIXED

DECIMAL(4,0).

In this case, the result is FIXED DECIMAL(15,11), 0005.00000000000. Adding

1000 to this gives 1005.00000000000 (FIXED DECIMAL(15,11)).

A = 1000 + 0015 / 3;

would have worked just as well.

However, this is not a good solution, because it is confusing.

This is a basic problem with fixed-point, non-integer arithmetic. There

is no possible set

of rules for the language to follow that will not either cause

FIXEDOVERFLOW in some

cases or give incorrect results in some cases. Changing the upper limit

of precision to some

number larger than 15 wouldn't help; the result of a fixed-point

division is always given the

upper-limit precision, whatever that is. Most languages "solve" the

problem by supporting

only integers and floating-point numbers. COBOL "solves" the problem by

not having

any rules; the compiler designer is free to do whatever he wants; that's

why all books of

advice about programming in COBOL tell you never to use the COMPUTE

statement -- it

gives essentially random results. Ada solves the problem by forcing the

programmer to

specify what precision he wishes the result of a division (or

multiplication) to be when he

is working with fixed-point, non-integer data.

The safe thing to do in PL/I is to use the same strategy as Ada. PL/I

has MULTIPLY

and DIVIDE built-in functions (ADD, too, and also SUBTRACT on some

compilers)

that allow you to control the precision of your result.

A = 1000 + DIVIDE (15, 3, 6, 4);

for example, will divide 15 by 3 and put the result into FIXED DECIMAL(6,4).

That will give a result of 05.0000. When that is added to 1000, the

final result will

be 01005.0000.

Instead of DIVIDE, you can use the PREC or FIXED or DECIMAL built-in

functions.

A = 1000 + PREC (15 / 3, 6, 4);

The numbers you use don't have to be 6 and 4. But the last number must

be no more

than 11, so that the final result will fit in FIXED DECIMAL(15,11).

"The poor have sometimes objected to being governed badly;

the rich have always objected to being governed at all."

-- G. K. Chesterton, "The Man Who Was Thursday"