# Compaq COBOL
User Manual

Previous | Contents | Index

# Chapter 2
Handling Numeric Data

Numeric data in Compaq COBOL is evaluated with respect to the algebraic value of the operands.

This chapter describes the following topics concerning numeric data handling:

- How the compiler stores numeric data ( Section 2.1)
- Specifying alignment ( Section 2.2)
- Sign conventions ( Section 2.3)
- Invalid values in numeric items ( Section 2.4)
- Evaluating numeric items ( Section 2.5)
- Using the MOVE statement ( Section 2.6)
- Using the arithmetic statements ( Section 2.7)

# 2.1 How the Compiler Stores Numeric Data

Understanding how data is stored will help you in the following situations:

- When you define data items to participate in group moves or to be the subject of a REDEFINES clause
- When you move a complex record consisting of several levels of subordination, to be sure that the receiving item is large enough to prevent data truncation
- When you need to use data storage concepts to minimize storage space, particularly when the data file is large

The storage considerations applicable to tables are described in Chapter 4.

For each numeric data item, Compaq COBOL stores the numeric value, and a sign (if an S appears in the PICTURE clause).

The USAGE clause of a numeric data item specifies the data's internal format in storage. When you do not specify a USAGE clause, the default usage is DISPLAY. For further information about internal representations, refer to the USAGE clause tables in the Compaq COBOL Reference Manual.

# 2.2 Specifying Alignment

In Compaq COBOL, all records, and elementary items with level 01 or 77, begin at an address that is a multiple of 8 bytes (a quadword boundary). By default, the Compaq COBOL compiler will locate a subordinate data item at the next unassigned byte location. However, the SYNCHRONIZED clause, the `-align` flag (on Tru64 UNIX), the /ALIGNMENT qualifier (on OpenVMS Alpha), and alignment directives can be used to modify this behavior, causing some numeric data items to be aligned on a 2-, 4-, or 8-byte boundary. You can thus tune data alignment for optimum performance, compatibility with Compaq COBOL for OpenVMS VAX, or flexibility. (See Chapter 16, Managing Memory and Data Access and Chapter 15, Optimizing Your Compaq COBOL Program in this manual, and refer to the SYNCHRONIZED clause in the Compaq COBOL Reference Manual for a complete discussion of alignment.)

# 2.3 Sign Conventions

Compaq COBOL numeric items can be signed or unsigned. Note the following sign conventions:

- If you store a signed result in an unsigned item, only the absolute value is stored. Thus, unsigned items only contain the value zero or a positive value.
- The way Compaq COBOL stores signed results in signed data items depends on the usage and the presence or absence of the SIGN clause.
- When an unsigned result is stored in a signed data item, the sign of the stored result is positive.

Do not use unsigned numeric items in arithmetic operations. They usually cause programming errors and are handled less efficiently than signed numeric items. The following example shows how unsigned numeric items can cause errors:

    DATA DIVISION
    .
    .
    .
    01 A PIC 9(5) COMP VALUE 2.
    01 B PIC 9(5) COMP VALUE 5.

Then:

    SUBTRACT B FROM A.       (A = 3)

    SUBTRACT 1 FROM A.       (A = 2)

However:

    COMPUTE A = (A - B) - 1    (A = 4)

The absence of signs for the numeric items A and B results in two different answers after parallel arithmetic operations have been done. This occurs because internal temporaries (required by the COMPUTE statement) are signed. Thus, the result of (A--B) within the COMPUTE statement is --3; --3 minus 1 is --4 and the value of A then becomes 4.

# 2.4 Invalid Values in Numeric Items

All Compaq COBOL arithmetic operations store valid values in their result items. However, it is possible, through group moves or REDEFINES, to store data in numeric items that do not conform to the data definitions of those items.

The results of arithmetic operations that use invalid data in numeric items are undefined. You can use the `-check decimal` flag (on the Tru64 UNIX operating system) or the /CHECK=DECIMAL qualifier (on the OpenVMS Alpha operating system) to validate numeric digits when using display numeric items in a numeric context; note that this flag or qualifier causes a program to terminate abnormally if there is invalid data. In the case of data with blanks (typically, records in a file), you can use the `-convert leading_blanks` flag (on Tru64 UNIX) or the /CONVERT qualifier (on OpenVMS Alpha) to change all blanks to zeroes before performing the arithmetic operation. If you specify both the `-check` decimal and the `-convert leading_blanks` flags (on Tru64 UNIX), or both the /CHECK=DECIMAL and the /CONVERT qualifiers on OpenVMS Alpha, the conversion of blanks will be done prior to the validation of the resulting numeric digits. Note that the use of either or both of these qualifiers increases the execution time of the program. Refer to Compaq COBOL online help (at the OpenVMS Alpha system prompt), or `man cobol` (on Tru64 UNIX) for more information.

# 2.5 Evaluating Numeric Items

Compaq COBOL provides several kinds of conditional expressions used for evaluating numeric items. These conditional expressions include the following:

- The numeric relation condition that compares the item's contents to another numeric value
- The sign condition that examines the item's sign to see if it is positive or negative
- The class condition that inspects the item's digit positions for valid numeric characters
- The success/failure condition that checks the return status codes of COBOL and non-COBOL procedures for success or failure conditions

The following sections explain these conditional expressions in detail.

## 2.5.1 Numeric Relation Test

A numeric relation test compares two numeric quantities and determines if the specified relation between them is true. For example, the following statement compares item FIELD1 to item FIELD2 and determines if the numeric value of FIELD1 is greater than the numeric value of FIELD2:

    IF FIELD1 > FIELD2 ...

If the relation condition is true, the program control takes the true path of the statement.

Table 2-1 describes the relational operators.

Table 2-1 Numeric Relational Operator Descriptions
Operator | Description
--- | ---
IS [NOT] GREATER THAN IS [NOT] > | The first operand is greater than (or not greater than) the second operand.
IS [NOT] LESS THAN IS [NOT] < | The first operand is less than (or not less than) the second operand.
IS [NOT] EQUAL TO IS [NOT] = | The first operand is equal to (or not equal to) the second operand.
IS GREATER THAN OR EQUAL TO IS >= | The first operand is greater than or equal to the second operand.
IS LESS THAN OR EQUAL TO IS <= | The first operand is less than or equal to the second operand.

Comparison of two numeric operands is valid regardless of their USAGE clauses.

The length of the literal or arithmetic expression operands (in terms of the number of digits represented) is not significant. Zero is a unique value, regardless of the sign.

Unsigned numeric operands are assumed to be positive for comparison. The results of relation tests involving invalid (nonnumeric) data in a numeric item are undefined.

## 2.5.2 Numeric Sign Test

The sign test compares a numeric quantity to zero and determines if it is greater than (positive), less than (negative), or equal to zero. Both the relation test and the sign test can perform this function. For example, consider the following relation test:

    IF FIELD1 > 0 ...

Now consider the following sign test:

    IF FIELD1 POSITIVE ...

Both of these tests accomplish the same thing and always arrive at the same result. The sign test, however, shortens the statement and makes it more obvious that the sign is being tested.

Table 2-2 shows the sign tests and their equivalent relation tests.

Table 2-2 Sign Tests
Sign Test | Equivalent Relation Test
--- | ---
IF FIELD1 POSITIVE ... | IF FIELD1 > 0 ...
IF FIELD1 NOT POSITIVE ... | IF FIELD1 NOT > 0 ...
IF FIELD1 NEGATIVE ... | IF FIELD1 < 0 ...
IF FIELD1 NOT NEGATIVE ... | IF FIELD1 NOT < 0 ...
IF FIELD1 ZERO ... | IF FIELD1 = 0 ...
IF FIELD1 NOT ZERO ... | IF FIELD1 NOT = 0 ...

Sign tests do not execute faster or slower than relation tests because the compiler substitutes the equivalent relation test for every correctly written sign test.

## 2.5.3 Numeric Class Tests

The class test inspects an item to determine if it contains numeric or alphabetic data. For example, the following statement determines if FIELD1 contains numeric data:

    IF FIELD1 IS NUMERIC ...

If the item is numeric, the test condition is true, and program control takes the true path of the statement.

Both relation and sign tests determine only if an item's contents are within a certain range. Therefore, certain items in newly prepared data can pass both the relation and sign tests and still contain data preparation errors.

The NUMERIC class test checks alphanumeric or numeric DISPLAY or COMP-3 usage items for valid numeric digits. If the item being tested contains a sign (whether carried as an overpunched character or as a separate character), the test checks it for a valid sign value. If the character position carrying the sign contains an invalid sign value, the NUMERIC class test rejects the item, and program control takes the false path of the IF statement.

The ALPHABETIC class test check is not valid for an operand described as numeric.

## 2.5.4 Success/Failure Tests

The success/failure condition tests the return status codes of COBOL and non-COBOL procedures for success or failure conditions. You test status-code-id as follows:

You can use the SET statement to initialize or alter the status of status-code-id (which must be a word or longword COMP integer represented by PIC 9(1 to 9) COMP or PIC S9(1 to 9) COMP), as follows:

The SET statement is typically in the called program, but the calling program may also SET the status of status-code-id. The SUCCESS class condition is true if status-code-id has been set to SUCCESS, otherwise it is false. The FAILURE class condition is true if status-code-id has been set to FAILURE, otherwise it is false. The results are unspecified if status-code is not set.

Example 2-1 shows the significant COBOL code relevant to a success/failure test.

Example 2-1 Success/Failure Test

    ...
    PROGRAM-ID.  MAIN-PROG.
    ...
    O1   RETURN-STATUS      PIC S9(9) COMP.
    ...
        CALL "PROG-1" GIVING RETURN-STATUS.
        IF RETURN-STATUS IS FAILURE PERFORM FAILURE-ROUTINE.
    ...
    PROGRAM-ID. PROG-1.
    ....
    WORKING-STORAGE SECTION.
    01  RETURN-STATUS     PIC S9(9) COMP.
    PROCEDURE DIVISION GIVING RETURN-STATUS.
    ...
        IF NUM-1 = NUM-2
                  SET RETURN-STATUS TO SUCCESS
        ELSE
                  SET RETURN-STATUS TO FAILURE.
    ...
        EXIT PROGRAM.
    END PROGRAM PROG-1.
    END PROGRAM MAIN-PROG.

# 2.6 Using the MOVE Statement

The MOVE statement moves the contents of one item into another item. The following sample MOVE statement moves the contents of item FIELD1 into item FIELD2:

    MOVE FIELD1 TO FIELD2.

This section considers MOVE statements as applied to numeric and numeric edited data items.

## 2.6.1 Elementary Numeric Moves

If both items of a MOVE statement are elementary items and the receiving item is numeric, it is an elementary numeric move. The sending item can be numeric, alphanumeric, or numeric-edited. The elementary numeric move converts the data format of the sending item to the data format of the receiving item.

An alphanumeric sending item can be either of the following:

- An elementary alphanumeric data item
- Any alphanumeric literal other than the figurative constants SPACE, QUOTE, LOW-VALUE, or HIGH-VALUE

The elementary numeric move accepts the figurative constant ZERO and considers it to be equivalent to the numeric literal 0. It treats alphanumeric sending items as unsigned integers of DISPLAY usage.

When the sending item is numeric-edited, de-editing is applied to establish the unedited numeric value, which may be signed; then the unedited numeric value is moved to the receiving field.

If necessary, the numeric move operation converts the sending item to the data format of the receiving item and aligns the sending item's decimal point on that of the receiving item. Then it moves the sending item's digits to the corresponding receiving item's digits.

If the sending item has more digit positions than the receiving item, the decimal point alignment operation truncates the value of the sending item, with resulting loss of digits.

The end truncated (high-order or low-order) depends upon the number of sending item digit positions that find matches on each side of the receiving item's decimal point. If the receiving item has fewer digit positions on both sides of the decimal point, the operation truncates both ends of the sending item. Thus, if an item described as PIC 999V999 is moved to an item described as PIC 99V99, it loses one digit from the left end and one from the right end.

In the execution part of the following examples, the caret (^) indicates the assumed stored decimal point position:

    01 AMOUNT1 PIC 99V99 VALUE ZEROS.
       .
       .
       .
       MOVE 123.321 TO AMOUNT1.

    Before execution:  00^00
    After execution:   23^32

If the sending item has fewer digit positions than the receiving item, the move operation supplies zeros for all unfilled digit positions.

    01  TOTAL-AMT PIC 999V99 VALUE ZEROS.
        .
        .
        .
        MOVE 1 TO TOTAL-AMT.

    Before execution:   000^00

    After execution:    001^00

The following statements produce the same results:

    MOVE 001.00 TO TOTAL-AMT.

    MOVE "1" TO TOTAL-AMT.

Consider the following two MOVE statements and their truncating and zero-filling effects:

         Statement                 TOTAL-AMT After Execution

    MOVE 00100 TO TOTAL-AMT                  100^00
    MOVE "00100" TO TOTAL-AMT                100^00

Literals with leading or trailing zeros have no advantage in space or execution speed in Compaq COBOL, and the zeros are often lost by decimal point alignment.

The MOVE statement's receiving item dictates how the sign will be moved. When the receiving item is a signed numeric item, the sign from the sending item is placed in it. If the sending item is unsigned, and the receiving item is signed, a positive sign is placed in the receiving item. If the sending item is signed and the receiving item is unsigned, the absolute value of the sending item is moved to the receiving item.

## 2.6.2 Elementary Numeric-Edited Moves

An elementary numeric move to a numeric-edited receiving item is considered an elementary numeric-edited move. The sending item of an elementary numeric-edited move can be numeric, numeric-edited, or alphanumeric. When the sending item is numeric-edited, de-editing is applied to establish the item's unedited numeric value, which may be signed; then the unedited numeric value is moved to the receiving field. Alphanumeric sending items in numeric-edited moves are considered unsigned DISPLAY usage integers.

A numeric-edited item PICTURE can contain 9, V, and P, but to qualify as numeric-edited, it must also contain one or more of the following editing symbols:

> Z
> B
> Asterisk (*)
> Period (.)
> Plus sign (+)
> Minus sign (--)
> CR
> DB
> Currency symbol
> Slash (/)
> Comma (,)
> Zero (0)

For a complete description of these symbols, refer to the Compaq COBOL Reference Manual.

The numeric-edited move operation first converts the sending item to DISPLAY usage and aligns both items on their decimal point locations. The sending item is truncated or zero-filled until it has the same number of digit positions on both sides of the decimal point as the receiving item. The operation then moves the sending item to the receiving item, following the Compaq COBOL editing rules.

The rules allow the numeric-edited move operation to perform any of the following editing functions:

- Replace leading zeros with either spaces or asterisks.
- Float a currency sign and a plus or minus sign through suppressed zeros, inserting the sign at either end of the item.
- Insert zeros, spaces, slashes, and/or the symbols CR or DB.
- Insert commas and a decimal point (or decimal points and a comma if DECIMAL-POINT IS COMMA).

Table 2-3 illustrates several of these functions, which are invoked by the statement:

    MOVE FLD-B TO TOTAL-AMT.

Assume that FLD-B is described as S9999V99. Note that the caret (^) indicates an assumed decimal point in Table 2-3. In all but two of the examples, the sign of FLD-B is leading separate. Trailing overpunch signs (the sign of the number encoded into the rightmost digit) are used in the other two FLD-B data examples.

Table 2-3 Numeric Editing
FLD-B | TOTAL-AMT
--- | ---
| PICTURE String | Contents After MOVE
+0023^00 | ZZZZ.99 | 23.00
-0023^00 | ZZZZ.99 | 23.00
0085^9P | ++++.99 | -85.97
+1234^00 | Z,ZZZ.99 | 1,234.00
+0012^34 | $,$$$.99 | $12.34
+0000^34 | $,$$9.99 | $0.34
+1234^00 | $$,$$$.99 | $1,234.00
+0012^34 | $$9,999.99 | $0,012.34
+0012^34 | $$$$,$$$.99 | $12.34
+0000^00 | $$$,$$$.$$ |
0012^3M | ++++.99 | -12.34
+0012^34 | $***,***.99 | $*****12.34
+1234^56 | Z,ZZZ.99+ | 1,234.56+
-6543^21 | $,$$$,$$$.99DB | $6,543.21DB 1

1The output includes DB if a negative value is moved.

The currency symbol ($ or other currency sign) and the editing sign control symbols (+ and --) are the only floating symbols. To float a symbol, enter a string of two or more occurrences of that symbol, one for each character position over which you want the symbol to float.

Previous | Next | Contents | Index