Search code examples
aixzospl-i

IBM PL/I: Using Fixed variable


I came across a code recommendation for IBM PL/I: do not create fixed type variable. The example of wrong code is:

DECLARE avar FIXED BIN; 

while the correct code given is:

DECLARE avar BIN; 

I wanted to know whether this is correct recommendation because there are way too many occurrences in the code, existing and new, where "Fixed" is and will be used. And if it is correct recommendation, should it only be applicable to "BIN" or BIN(n,m) as well.


Solution

  • I can only guess as to the rationale for this "coding guideline".

    In PL/1, a number can be binary (BIN) or decimal (DEC). Generally when we think of numbers, we think in decimal rather than binary. So we think of numbers like 123.45 (FIXED DEC (5,2)) not 1001101.011B (FIXED BIN (10,3)). Fixed binary is an odd duck, and we generally don't understand it intuitively. Can you tell me what the afore mentioned fixed binary number is in decimal? Maybe the integer part, but what about the decimal part?

    Let's break it down:

    1001101.011B
    ||||||| ||+---> 1/8          .125
    ||||||| |+----> 1/4          .25
    ||||||| +-----> 1/2         0.0
    ||||||+-------> 1           1
    |||||+--------> 2           0
    ||||+---------> 4           4
    |||+----------> 8           8
    ||+-----------> 16          0
    |+------------> 32          0
    +-------------> 64         64
                               ======
                               77.375
    

    Did you get that? Going the other way you can convert 123.45 to fixed binary like this:

    Integer       Fractional
     Part          Part
    
    123.45       .00000000                             .45
    -64           |||||||+--> 1/256 = .00390625       -.25
    ------        ||||||+---> 1/128 = .0078125        ----
     59.45        |||||+----> 1/64  = .015625          .2
    -32           ||||+-----> 1/32  = .03125          -.125
    ------        |||+------> 1/16  = .0625           -----
     27.45        ||+-------> 1/8   = .125             .075
    -16           |+--------> 1/4   = .25             -.0625
    ------        +---------> 1/2   = .5              ------
     11.45                                             .0125
     -8                                               -.0078125
    ------                                            ---------
      3.45                                             .0046875
     -2                                               -.00390625
    ------                                            ----------
      1.45                                             .00071825  <--+
     -1                                                              |
                                                                     |
    = 1111011B                                      = .01110011B (and it is not exact)
    
    So 123.45 ~ 1111011.01110011B
    

    So FIXED BIN probably not a good idea. Not every fixed decimal number can be represented in FIXED BIN, and it is not really intuitive.

    If FIXED/FLOAT is not specified, FLOAT is the default. This in fact is how the floating point numbers you are likely used to are stored. So we can use it for our regular floating point calculations.

    As for the (p) vs. (p,q) question, (p) is for floating point, (p,q) is for fixed point, though q defaults to 0 when it is missing from the fixed point precision specification.

    You may then be wondering about DEC then. You probably should use FIXED DEC (p,q) to get what you are probably thinking about as a fixed point number like currency. These are likely encoded as Packed Decimal where each digit is stored in a nibble (4 bits) with a sign in the last nibble. So 123.45 would be stored as x'12 34 5f' where x'f' is positive or unsigned and x'd' is negative. The decimal point is assumed, not stored.

    So to summarize, for exact calculations use FIXED DEC, and for floating point calculation use BIN or FLOAT BIN.