MainframeMaster

ZD (Zoned Decimal) Format

In DFSORT, ZD stands for zoned decimal. A zoned decimal field stores one decimal digit per byte: each byte has a "zone" in the high nibble (often X'F' in EBCDIC) and the digit (0–9) in the low nibble. The sign is encoded in the last byte (or sometimes the first, depending on COBOL): the zone nibble indicates positive (e.g. F or C) or negative (e.g. D). This is how COBOL USAGE DISPLAY numeric data is stored (PIC 9(n) or S9(n) DISPLAY). When you specify ZD in SORT FIELDS, DFSORT interprets the key as a signed decimal number and compares numeric value—so 9 comes before 10, and negative numbers sort before positive in ascending order. Using CH on the same data compares raw bytes (character order), which can give wrong numeric order; using PD expects two digits per byte and is wrong for zoned data. This page explains ZD in detail: byte layout, sign, when to use ZD, and how it differs from CH, PD, and BI.

Data Types & Formats
Progress0 of 0 lessons

What Zoned Decimal Looks Like

In zoned decimal, each byte represents one digit. The high nibble (first 4 bits) is the "zone"—in EBCDIC, X'F' is common for unsigned digits, and the zone is also used for the sign in the last byte. The low nibble (last 4 bits) holds the digit 0–9. So the number 12345 in zoned form is five bytes: X'F1', X'F2', X'F3', X'F4', X'F5' for positive (F in zone of each byte). In EBCDIC, F1 is the character "1", F2 is "2", and so on—so zoned decimal looks like the EBCDIC representation of the digit string. For a negative number, the last byte has the sign in the zone: D in the zone (e.g. X'D5') often means negative, so -12345 might be X'F1F2F3F4D5'. So zoned decimal is "one digit per byte" with sign in the last (or first) byte's zone. DFSORT ZD tells the sort to read the key as this format and compare the numeric value.

Length in Bytes

For zoned decimal, the length in SORT FIELDS is the number of bytes the field occupies. Since there is one digit per byte, a 5-digit field is 5 bytes, a 7-digit field is 7 bytes, and so on. The sign is in one of those bytes (usually the last), so you do not add an extra byte for sign—the last byte holds both the last digit and the sign.

Zoned decimal length examples
Digits (e.g. PIC 9(n) or S9(n))Bytes (length in SORT FIELDS)Example
55PIC S9(5) DISPLAY → 5 bytes
77PIC 9(7) DISPLAY → 7 bytes
88PIC S9(8) DISPLAY (e.g. date) → 8 bytes

Syntax: SORT FIELDS with ZD

Use ZD in SORT FIELDS like this:

text
1
SORT FIELDS=(start,length,ZD,direction)
  • start — Starting position of the zoned decimal field (1-based).
  • length — Length in bytes (one byte per digit; sign in last byte).
  • ZD — Format: zoned decimal (signed).
  • direction — A for ascending, D for descending.

Example: sort by a 5-byte zoned amount at position 25, ascending:

text
1
SORT FIELDS=(25,5,ZD,A)

Example: sort by 8-byte date (YYYYMMDD) at position 1 then 4-byte zoned at 9, both ascending:

text
1
SORT FIELDS=(1,8,ZD,A,9,4,ZD,A)

When to Use ZD

Use ZD when the field is zoned decimal (one digit per byte)
Use caseReason
COBOL DISPLAY numeric (PIC 9(n), S9(n))Storage is one digit per byte, sign in last byte.
Numeric data stored as EBCDIC digitsOne character per digit; ZD interprets as number.
Dates or IDs stored as fixed-length digit strings with possible signZD handles sign and leading zeros correctly.

When Not to Use ZD

  • Packed decimal (COMP-3) — Use PD. Packed has two digits per byte; ZD expects one.
  • Binary (COMP/COMP-4) — Use BI or FI. Binary is not zoned decimal.
  • Pure character (names, codes with letters) — Use CH. ZD is for numeric interpretation.

ZD vs CH: Why Use ZD for Numbers

If a field contains only digits (and sign), you might think CH would work—and for fixed-length positive digit strings it sometimes does, because in EBCDIC the codes for 0–9 are in ascending order. But CH compares byte-by-byte and does not interpret the sign. A negative number has a different zone in the last byte (e.g. D); compared as character, that can sort in the wrong place relative to positive numbers. Also, if lengths ever differ (e.g. "9" vs "10"), CH puts "10" before "9" because the first byte "1" is less than "9" in EBCDIC. ZD interprets the whole field as one signed number, so 9 comes before 10 and negatives sort correctly. So for any zoned decimal numeric key, prefer ZD over CH for correct numeric order.

ZD vs PD: Different Storage

PD (packed decimal) stores two digits per byte. So the number 12345 in packed form is three bytes (X'12345C'), while in zoned form it is five bytes (X'F1F2F3F4F5'). If you use ZD on a packed field, DFSORT will treat those three bytes as a 3-digit zoned number and read the wrong value. If you use PD on a zoned field, it will expect two digits per byte and again get the wrong value. So you must know the actual storage: one digit per byte → ZD; two digits per byte (COMP-3) → PD.

Sign Conventions (EBCDIC)

In the last byte of a zoned decimal field, the low nibble is the last digit and the high nibble (zone) is the sign. Common EBCDIC conventions: F or C for positive, D for negative. Some COBOL variants use SIGN LEADING (sign in the first byte) or other encodings. DFSORT understands the usual conventions and compares the numeric value correctly. Negative numbers sort before zero, which sorts before positive, in ascending order.

ZD in INCLUDE, OMIT, and Build Statements

Wherever DFSORT needs to interpret a numeric field—in INCLUDE/OMIT conditions or in INREC/OUTREC—you specify the format. For a zoned decimal field, use ZD so that numeric comparisons (e.g. greater than 100, equal to zero) and any arithmetic use the correct value. Using CH would compare the bytes as character; using PD would misinterpret the layout.

Explain It Like I'm Five

Imagine writing a number with one digit in each box: 1, 2, 3, 4, 5 in five boxes. The last box also has a little mark for plus or minus. That is zoned decimal. ZD is the rule that tells the sort: "this part of the record is a number written that way." So the sort puts the smaller numbers first (or bigger first) the way we expect: 9 before 10, and minus 5 before plus 5. If we used the "character" rule (CH), the sort would just look at the boxes as letters and might put 10 before 9. So we use ZD when the key is a number stored with one digit per box (like many numbers you see in mainframe files that look like normal digits when printed).

Exercises

  1. Your record has PIC S9(7) DISPLAY at position 40. What length do you use in SORT FIELDS and what is the full SORT FIELDS line for ascending?
  2. Why does "10" sort before "9" when you use CH? How does ZD fix this?
  3. A field at position 1 is 8 bytes and contains a date YYYYMMDD as EBCDIC digits. Could you use CH? What is the advantage of ZD?
  4. How many bytes does PIC 9(10) DISPLAY occupy? What about PIC S9(10) DISPLAY?

Quiz

Test Your Knowledge

1. What does ZD mean in DFSORT?

  • Zero default
  • Zoned decimal: one digit per byte, sign in the last (or first) byte; DFSORT compares numeric value
  • Zone descriptor
  • Zero length default

2. A COBOL field is PIC S9(5) DISPLAY. What length do you specify in SORT FIELDS?

  • 9 bytes
  • 5 bytes (one per digit); sign is in the last byte
  • 3 bytes
  • 4 bytes

3. Where is the sign in standard EBCDIC zoned decimal?

  • In a separate byte
  • In the high nibble (zone) of the last byte: F/C for positive, D for negative
  • In the first byte only
  • ZD has no sign

4. When can CH give the same order as ZD for a numeric field?

  • Never
  • When the field is fixed-length, positive only, same length for all records (e.g. 8-digit date); then EBCDIC digit order can match numeric order. ZD is safer for signed or variable-length.
  • Only when OPTION EQUALS is used
  • Only for the primary key

5. What happens if you use ZD for a packed decimal (COMP-3) field?

  • It works the same
  • Packed has two digits per byte; zoned has one. DFSORT misinterprets the bytes and sort order is wrong.
  • Only negative values are wrong
  • ZD is faster so it is preferred