MainframeMaster

PD (Packed Decimal) Format

In DFSORT, PD stands for packed decimal. A packed decimal field stores two decimal digits per byte: each byte is split into two 4-bit nibbles, and each nibble holds a digit 0–9. The last byte holds one digit in one nibble and the sign in the other (e.g. C or F for positive, D for negative). This is exactly how COBOL COMP-3 (and equivalent) numeric fields are 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 7-digit COMP-3). 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 PD format in detail: nibbles, sign, length calculation, when to use PD, and how it differs from ZD, CH, and BI.

Data Types & Formats
Progress0 of 0 lessons

What Packed Decimal Looks Like

In packed decimal, each byte holds two digits. The high nibble (first 4 bits) holds one digit and the low nibble (last 4 bits) holds another. So the byte X'12' represents the digits 1 and 2. The number 12345 in packed form is typically stored as three bytes: X'12', X'34', and X'5C'—where the last byte has 5 in one nibble and C (positive sign) in the other. So we write it as X'12345C'. For -12345, the last byte would be X'5D' (D = negative). This is not the same as the character string "12345", which in EBCDIC would be five bytes: X'F1F2F3F4F5' (one byte per character). So packed decimal is more compact than zoned (one digit per byte) and has a different byte layout. DFSORT PD tells the sort to read the key as this packed format and compare the numeric value.

Length in Bytes

The length you specify in SORT FIELDS for PD is always the number of bytes the field occupies. To compute it from the number of digits:

  • Packed decimal stores two digits per byte, except the last byte holds one digit plus sign.
  • So: bytes = (number of digits + 1) / 2, rounded up. The +1 is for the sign nibble.
Packed decimal byte length examples
Digits (e.g. PIC S9(n))Bytes (length in SORT FIELDS)Example
53PIC S9(5) COMP-3 → (5+1)/2 = 3
74PIC S9(7) COMP-3 → (7+1)/2 = 4
95PIC S9(9) COMP-3 → (9+1)/2 = 5
158PIC S9(15) COMP-3 → (15+1)/2 = 8

If you are unsure, check your COBOL copybook or record layout: the length in bytes is what you use in SORT FIELDS, not the digit count.

Syntax: SORT FIELDS with PD

Use PD in SORT FIELDS like this:

text
1
SORT FIELDS=(start,length,PD,direction)
  • start — Starting position of the packed decimal field (1-based).
  • length — Length in bytes (e.g. 4 for a 7-digit COMP-3).
  • PD — Format: packed decimal (signed).
  • direction — A for ascending, D for descending.

Example: sort by a 4-byte packed amount at position 30, descending:

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

Example: primary key character at 1–10, secondary key packed at 11–14, both ascending:

text
1
SORT FIELDS=(1,10,CH,A,11,4,PD,A)

When to Use PD

Use PD when the field is packed decimal
Use caseReason
COBOL COMP-3 (or equivalent)Storage is two digits per byte, sign in last nibble.
Amounts, quantities, totals in packed formMany mainframe files use COMP-3 for numeric fields.
Record layout says "packed" or "COMP-3"Match the format to the actual storage.

When Not to Use PD

  • Zoned decimal (DISPLAY) — One digit per byte. Use ZD. Using PD on zoned data misinterprets the bytes.
  • Character or EBCDIC digits — Use CH or ZD. Packed bytes are not character codes.
  • Binary (COMP/COMP-4) — Use BI or FI. Binary is base-2 integer, not packed decimal.

PD vs ZD: Why It Matters

ZD (zoned decimal) is for data stored with one digit per byte—like COBOL DISPLAY numeric. Each byte is an EBCDIC character for a digit (0xF0–0xF9), and the sign is in the zone (high nibble) of the last byte. So the number 12345 in zoned form is five bytes: X'F1F2F3F4F5' (positive) or X'F1F2F3F4D5' (negative, D in zone of last byte). In packed form, 12345 is X'12345C' (three bytes). The byte sequences are completely different. If you use PD on a zoned field, DFSORT will read the wrong value (it expects two digits per byte) and the sort order will be wrong. If you use ZD on a packed field, same problem. So you must know how the field is actually stored and choose PD or ZD accordingly.

Sign Conventions

In the last byte of a packed decimal field, one nibble is the last digit (0–9) and the other is the sign. Common conventions on the mainframe: C and F for positive, D for negative. Some systems use other values. DFSORT understands the usual conventions and compares the numeric value correctly (negative less than zero less than positive). You do not need to change the data—just specify PD and the correct length.

PD in INREC, OUTREC, and INCLUDE/OMIT

Wherever DFSORT needs to interpret a numeric field—in INCLUDE/OMIT comparisons, or when building or editing in INREC/OUTREC—you specify the format. For a packed decimal field, use PD so that numeric comparisons and arithmetic (if supported) use the correct value. For example, to omit records where a 4-byte packed amount at position 20 is zero or negative, you would use a numeric test with format PD; using CH or ZD would misinterpret the bytes.

Explain It Like I'm Five

Imagine saving numbers by putting two digits in each little box (byte). So the number 12345 fits in three boxes: 12, 34, and 5 with a plus sign. That is packed decimal. The computer knows how to read it: first box 12, second 34, third 5 and plus. PD is the rule that tells the sort: "this part of the record is saved that way." So the sort compares the real numbers (smaller first or bigger first). If we used the "character" rule (CH), the sort would look at the boxes as if they were letters and get the order wrong. So we use PD when the key is stored in that compact two-digits-per-box form, like many numbers in mainframe files.

Exercises

  1. Your record has PIC S9(9) COMP-3 at position 40. What is the length in bytes and what SORT FIELDS do you write for ascending numeric order?
  2. Why does using CH on a COMP-3 field produce wrong sort order? Explain in terms of how the bytes are stored (nibbles) vs how CH compares them.
  3. A field is stored as EBCDIC digits "00100" (five bytes). Should you use PD or ZD? What is the difference between that and a 3-byte packed value for 100?
  4. Calculate the byte length for PIC S9(11) COMP-3 and write SORT FIELDS=(50,?,PD,D) with the correct length.

Quiz

Test Your Knowledge

1. What does PD mean in DFSORT?

  • Print decimal
  • Packed decimal: the field is stored with two digits per byte and a sign in the last nibble; DFSORT compares numeric value
  • Position dependent
  • Primary key default

2. A COBOL field is PIC S9(7) COMP-3. What length do you specify in SORT FIELDS?

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

3. Where is the sign stored in a packed decimal (PD) field?

  • First byte
  • Last byte: one nibble holds the last digit, the other holds the sign (e.g. C/F positive, D negative)
  • Separate sign byte
  • High-order bit of each byte

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

  • It works the same
  • DFSORT expects two digits per byte; zoned has one digit per byte. The bytes are misinterpreted and sort order is wrong.
  • Only negative values are wrong
  • PD is faster so it is preferred

5. Why must you not use CH for a COMP-3 (packed) field?

  • CH is slower
  • COMP-3 is packed decimal; the bytes are nibbles, not EBCDIC characters. CH compares raw bytes, which do not follow numeric order.
  • CH is only for the first key
  • COMP-3 requires PD and FI together