MainframeMaster

Packed Decimal Sorting

Packed decimal (PD) in DFSORT is the format you use when your sort key is stored in packed decimal form: two decimal digits per byte, with each nibble (4 bits) holding a digit 0–9, and the last byte holding one digit plus the sign (e.g. C or F for positive, D for negative). This is exactly how COBOL COMP-3 (and equivalent) data is stored. When you specify PD in SORT FIELDS=, DFSORT interprets the key as a signed decimal number and compares numeric value. The length you give is the number of bytes (e.g. 4 bytes for a typical PIC S9(7) COMP-3, which holds 7 digits plus sign). Using CH or ZD on packed data—or PD on zoned or character data—produces wrong sort order because the byte layout is different. This page explains the packed decimal layout, when to use PD, how to compute length, and how it differs from ZD and CH.

SORT Statement Deep Dive
Progress0 of 0 lessons

What Is Packed Decimal?

Packed decimal stores decimal digits in a compact form: two digits per byte. Each byte has two 4-bit nibbles; each nibble holds a digit 0–9. So the byte X'12' holds the digits 1 and 2. The number 12345 in packed form might be stored as X'12345C' (3 bytes): first byte 12, second 34, third 5 and sign C (positive). The last byte has only one digit in one nibble and the sign in the other nibble. In EBCDIC/mainframe convention, C and F often mean positive, D means negative. So -12345 might be X'12345D'. COBOL COMP-3 uses this format. DFSORT PD tells the sort to interpret the key as this packed signed decimal and compare by numeric value.

When to Use PD

Use PD whenever the sort key is stored in packed decimal form. That includes: (1) COBOL fields defined as PIC S9(n) COMP-3 (or PIC 9(n) COMP-3, or equivalent); (2) Any numeric field that you know is in packed format (two digits per byte, sign in last nibble); (3) Legacy files where the layout says the field is "packed" or "COMP-3." Do not use PD for zoned decimal (DISPLAY)—use ZD. Do not use PD for character or display-digit data (e.g. X'F3F0F0' for "300" as characters)—use CH or ZD. Using PD on the wrong storage type causes DFSORT to misinterpret the bytes and produces incorrect or meaningless sort order.

Byte Length: How Many Bytes?

Packed decimal uses (digits + 1) / 2 bytes (rounded up). So: 1 digit + sign = 1 byte; 2 digits + sign = 2 bytes; 3–4 digits = 2 bytes; 5–6 digits = 3 bytes; 7–8 digits = 4 bytes; 9–10 digits = 5 bytes. For example, PIC S9(7) COMP-3 has 7 digits plus sign, so 4 bytes. In SORT FIELDS you specify the length in bytes: SORT FIELDS=(21,4,PD,A) for a 4-byte packed field starting at position 21. Getting the length wrong (e.g. 7 instead of 4) will include extra bytes that are not part of the number and can corrupt the comparison.

Sign in the Last Nibble

The sign is in the last (rightmost) byte of the packed field, in one of the two nibbles. Typically the high nibble holds the last digit and the low nibble holds the sign (or vice versa depending on convention). Common EBCDIC sign values: X'C' and X'F' for positive, X'D' for negative. DFSORT, when using PD, reads the full key as a signed packed decimal and compares numeric value, so negative numbers sort before positive in ascending order. The exact nibble order (digit/sign) is part of the packed format definition; DFSORT follows the standard mainframe convention.

PD vs ZD: Do Not Confuse

Zoned decimal (ZD) has one digit per byte (like DISPLAY). Packed decimal (PD) has two digits per byte. So the same numeric value has a completely different byte representation. For example, the number 12 in zoned might be X'F1F2' (2 bytes); in packed it is X'12C' or X'012C' (1 or 2 bytes). If you specify PD for a zoned field, DFSORT will read two digits per byte and get wrong values. If you specify ZD for a packed field, it will read one digit per byte and again get wrong order. Always match the format to the actual storage: COMP-3 / packed → PD; DISPLAY / zoned → ZD.

PD vs CH: Why CH Is Wrong for Packed

If you sort a packed decimal field using CH, DFSORT compares the raw byte values. In packed form, the bytes are nibbles (e.g. X'01', X'23', X'45', X'6C' for 123456+). Those byte values do not increase in numeric order—the relationship between byte value and numeric value is not linear. So you can get 100 before 20, or seemingly random order. For correct numeric order you must use PD so that DFSORT decodes the packed value and compares the actual number.

Examples

Sort by a 4-byte packed decimal amount at position 25, descending:

text
1
SORT FIELDS=(25,4,PD,D)

Sort by bytes 1–20 character (e.g. name), then by bytes 21–24 packed decimal ascending (e.g. ID or amount):

text
1
SORT FIELDS=(1,20,CH,A,21,4,PD,A)

For a PIC S9(5) COMP-3 field (3 bytes: 5 digits + sign) at position 40:

text
1
SORT FIELDS=(40,3,PD,A)

Copybook and Length Verification

When in doubt, check the COBOL copybook or program that defines the file. PIC S9(7) COMP-3 → 4 bytes, use PD. PIC S9(5) COMP-3 → 3 bytes, use PD. The formula (digits+1)/2 rounded up gives the byte length. Specify that length in SORT FIELDS so the key is exactly the packed field and no more.

Explain It Like I'm Five

Packed decimal is like squeezing two numbers into one box: the tens and ones go in the same box. The sort program needs to know "this is that kind of squeezed number" so it can read the real value (e.g. 12345) and put the records in order. If the program thought the boxes were just letters, it would get the order wrong. So we say "PD" so it reads the squeezed number correctly and sorts from smallest to biggest (or biggest to smallest).

Exercises

  1. A field is PIC S9(9) COMP-3. How many bytes? Write SORT FIELDS= for that field at position 30, ascending.
  2. Why must you not use CH for a COMP-3 amount field?
  3. Record has name 1–25, amount COMP-3 at 26–29 (4 bytes). Write SORT FIELDS= to sort by amount descending, then by name ascending.
  4. What goes wrong if the data is actually zoned (DISPLAY) but you specify PD?

Quiz

Test Your Knowledge

1. What COBOL data type does DFSORT PD (packed decimal) correspond to?

  • DISPLAY
  • COMP
  • COMP-3
  • COMP-4

2. How many bytes does a PIC S9(7) COMP-3 field occupy?

  • 7 bytes
  • 4 bytes ( (7+1)/2 = 4 )
  • 3 bytes
  • 8 bytes

3. Where is the sign stored in packed decimal?

  • In the first byte
  • In the high nibble of the last byte
  • In the low nibble of the last byte (with the sign in that nibble)
  • In a separate byte

4. What happens if you use PD for a field that is actually zoned decimal (DISPLAY)?

  • It works the same
  • DFSORT misinterprets the bytes (expects two digits per byte); sort order will be wrong
  • Only descending fails
  • PD is faster

5. For SORT FIELDS with PD, what does the length refer to?

  • Number of digits
  • Number of bytes the key occupies
  • Number of nibbles
  • Number of keys