PL/I is a very forgiving language—the programmer can code nearly every type of operand for an operation and have it compile and (sometimes) execute. For example, they can add a fixed-point numeric value, a bit string, and a character string. [e.g. 3.5 + '10'b + ' 433E5'] While not producing the best code, this will operate correctly, as long as the character string represents a valid number. Occasionally, however, PL/I can produce completely unexpected results.
One case of this is conversion of a numeric value to a bit string. The results, although fully documented, were so surprising that I checked the code with two compilers to make sure it wasn't an error.
The two cases I tried assigned values to a string declared as BIT(8). The first case assigned a variable declared as FIXED BINARY(7), and the second case assigned a numeric constant, by definition FIXED DECIMAL.
CASE 1:
DECLARE bt BIT(8);
DECLARE fx FIXED BINARY(7);
fixed = 3;
bt = fx.
The result is 6!
CASE 2:
DECLARE bt BIT(8);
bt = 3;
In this case, the result is 48! What is going on here?
As I said, this is completely documented.
In Case 2, "3" is a FIXED DECIMAL number with precision (1,0). Before converting it to BIT, it is first converted to FIXED BINARY. The precision of this value is CEIL( (1-0)*3.32 ), or 4. This converts to a bit string of length four, containing '0011'b. This string is then assigned, left justified—it is a string, after all—to bt, giving a result of '0011_0000'b, hex 30 or decimal 48.
In Case 1, fx is already FIXED BINARY(7,0) with a value of 3. UNSPEC(fx) is '0000_0011'b, but aha! the sign bit is dropped, so the source bit string is '0000011'b. This is then assigned to bt, again left justified, giving a result of '0000_0110'b, hex 06 or decimal 6.
ADDENDUM:
In case 1, if fx is declared FIXED BINARY(8) UNSIGNED, then bt will be 3, since there is no need to account for a sign bit.
Enjoy!