# Compaq COBOL
User Manual

Previous | Contents | Index

## 2.6.3 Subscripted Moves

Any item (other than a data item that is not subordinate to an OCCURS clause) of a MOVE statement can be subscripted, and the referenced item can be used to subscript another name in the same statement.

For additional information, see Section 3.6.4, Subscripted Moves in Chapter 3, Handling Nonnumeric Data .

## 2.6.4 Common Move Errors

Programmers most commonly make the following errors when writing MOVE statements:

- Placing an incorrect number of replacement characters in a numeric edited item
- Moving nonnumeric data into numeric items with group moves
- Trying to float the currency sign ($) or plus (+) insertion characters past the decimal point to force zero values to appear as .00 instead of spaces (use $$.99 or .99)
- Forgetting that the currency sign ($), plus sign (+), minus sign (--), CR, or DB insertion characters require one or two additional positions on the leftmost end that cannot be replaced by a digit (unlike the asterisk (*) insertion character, which can be completely replaced)

# 2.7 Using the Arithmetic Statements

The Compaq COBOL arithmetic statements allow programs to perform arithmetic operations on numeric data. Large values present various problems, and COBOL command qualifiers can help resolve or mitigate them. The following sections discuss these topics.

## 2.7.1 Temporary Work Items

Compaq COBOL allows numeric items and literals with up to 31 decimal digits on Alpha, and up to 18 decimal digits on VAX. (See Section 2.7.2 for more specific information.) It is quite easy to construct arithmetic expressions that produce too many digits.

Most forms of the arithmetic statements perform their operations in temporary work locations, then move the results to the receiving items, aligning the decimal points and truncating or zero-filling the resultant values. The actual size of a temporary work item (also called an intermediate result item) varies for each statement; it is determined at compile time, based on the sizes of the operands used by the statement and the arithmetic operation being performed. Should the temporary work item exceed the maximum size, truncation occurs.

On Alpha systems, the maximum temporary work item size is 31 digits for standard arithmetic and for native CIT4 arithmetic, and is 38 digits for some operations using native float or native CIT3. <>

On VAX systems, the situation is different. The temporary work item has two forms, a scaled integer form and a software floating-point form. The scaled integer form has a maximum size of 31 numeric digits for a program compiled with the /INSTRUCTION_SET = DECIMAL_STRING or GENERIC qualifier, and a maximum of 38 digits for /INSTRUCTION_SET = NODECIMAL_STRING. When the compiler determines that the size of the intermediate result exceeds the maximum scaled integer size, it uses a software floating-point intermediate item and keeps the most significant 18 digits (for all settings of the /INSTRUCTION_SET qualifier). <>

Programs should not arbitrarily specify sizes significantly larger than the values actually anticipated for the lifetime of the application. Although the generous limits in Compaq COBOL are useful for many applications, specifying many more digits than needed is likely to add extra processing cycles and complexity that is wasteful.

## 2.7.2 Standard and Native Arithmetic (Alpha)

Compaq COBOL supports two modes of arithmetic, standard and native. Standard arithmetic is preferable for greater precision with large values and for compatibility with other standard implementations of COBOL. These considerations are sometimes overridden by the need for compatibility with earlier versions of Compaq COBOL or for compatibility with Compaq COBOL for OpenVMS VAX, in which case native arithmetic is the appropriate mode.

Native arithmetic has three submodes: FLOAT, CIT3, and CIT4. (CIT stands for COBOL Intermediate Temporary).

You can specify the arithmetic mode and submode with the two COBOL command-line qualifiers /ARITHMETIC (or `-arithmetic` ) and /MATH_INTERMEDIATE (or `-math_intermediate` ). The use of these qualifiers is described in this section.

### 2.7.2.1 Using the /MATH_INTERMEDIATE Qualifier (Alpha)

You can specify the intermediate data type to be used when the result of an arithmetic operation cannot be represented exactly. This data type affects the truncation of the intermediate result and the consequent precision. It also affects compatibility of arithmetic results with previous versions of COBOL and other implementations of COBOL.

The three options of the /MATH_INTERMEDIATE (or `-math_intermediate` ) qualifier are FLOAT (the default), CIT3, and CIT4, as follows:

FLOAT | Selects double-precision binary floating-point for the intermediate data type. Intermediate values are truncated to the most significant 53 bits, with an 11-bit exponent, resulting in approximately 15 decimal digits of precision. FLOAT is the default, and it provides for compatibility with earlier versions of Compaq COBOL, but not with Compaq COBOL for OpenVMS VAX. FLOAT has been used since Version 1.0 of Compaq COBOL on Alpha.
CIT3 | Selects Cobol Intermediate Temporary (design 3) for the intermediate data type. Intermediate values are truncated to the most significant 18 decimal digits, with a 2-digit exponent. CIT3 provides for increased compatibility with Compaq COBOL for OpenVMS VAX; even with CIT3, however, there are still some differences, which are described in Section B.4.12.
CIT4 | Selects Cobol Intermediate Temporary (design 4) for the intermediate data type. Intermediate values are truncated to the most significant 32 decimal digits, with a 2-digit exponent. CIT4 has the greatest compatibility with the draft ANSI Standard. CIT4 is the option of choice for greatest precision and for conformance to future standards and compatibility with other implementations of COBOL. CIT4 is strongly recommended for programs that use numeric items with more than 18 digits or that have complicated expressions. In addition to the precision difference, CIT4 arithmetic has the same differences and restrictions as shown in Section B.4.12 for CIT3 arithmetic.

The default is /MATH_INTERMEDIATE=FLOAT (or `-math_intermediate float` ). If you specify /ARITHMETIC=STANDARD (discussed in Section 2.7.2.2), this will force /MATH_INTERMEDIATE=CIT4.

Example of Different Arithmetic Results (Alpha)

The following example illustrates the different results that you can get with FLOAT, CIT3, and CIT4:

    IDENTIFICATION DIVISION.
    PROGRAM-ID. MUL31.
    DATA DIVISION.
    WORKING-STORAGE SECTION.
    01  XD PIC S9(31) VALUE 3.
    01  YD PIC S9(31) VALUE 258718314234781388692555698765.
    01  ZD PIC S9(31).
    PROCEDURE DIVISION.
    0.
        MULTIPLY XD BY YD GIVING ZD
            ON SIZE ERROR DISPLAY "Size error raised"
            NOT ON SIZE ERROR DISPLAY ZD WITH CONVERSION.

The compiler relies on the number of digits implied by the pictures of decimal and integer operands. Here it assumes that XD has 31 digits and YD has 31 digits. The product could require 62 digits, which is larger than the largest fixed-point arithmetic type available to the compiler. Depending on the intermediate data type chosen, this program gets several different results.

                                                       Intermediate maintains
                MATH   ZD                              the most significant
                -----  ------------------------------  ----------------------
                FLOAT  776154942704344283789821739008  53 bits
                CIT3   776154942704344164000000000000  18 digits
                CIT4   776154942704344166077667096295  32 digits

Other Consequences of Intermediate Range Differences (Alpha)

Because each intermediate data type has a different maximum magnitude, an arithmetic statement can raise the size error condition with one arithmetic mode but not with another.

For example, the value +0.999 999 999 999 999 999E+99 (spaces added for readability) is representable in any of the intermediate data types. By contrast, the larger value +0.999 999 999 999 999 999 9E+99 cannot be represented in a CIT3 intermediate data item. Such an operation would cause an overflow, raising the size error condition. This value is representable, however, in a FLOAT or CIT4 intermediate data item; the size error condition would not be raised.

The value 1.0E+99 cannot be represented in either CIT3 or CIT4 form, but is representable in FLOAT form.

Similarly, because each intermediate data type has a different minimum magnitude, an arithmetic statement can raise the size error condition for underflow with one arithmetic mode but not another. (Underflow does not raise the size error condition when FLOAT arithmetic is used.)

A literal also can be valid with one arithmetic mode but not with another, resulting in different HIGHTRUNC and LOWTRUNC informational diagnostics. When a literal cannot be represented in an intermediate data item, the value used is undefined.

Arithmetic expressions in nonarithmetic statements are also affected. Nonarithmetic statements, such as the IF statement, allow arithmetic expressions to be used, but do not provide a mechanism like the ON SIZE ERROR phrase to detect errors in evaluation. If such an error occurs, the behavior of the statement is unpredictable; in the case of an IF statement, result of the comparison is undefined.

Similar considerations apply in other contexts, such as the use of arithmetic expressions as subscript expressions or reference-modification components.

### 2.7.2.2 Using the /ARITHMETIC Qualifier (Alpha)

You can specify /ARITHMETIC=NATIVE or STANDARD ( `-arithmetic native` or `standard` ) on the COBOL command line to control whether native arithmetic or standard arithmetic is used to evaluate arithmetic operations and statements. These options have the following effects:

NATIVE | Arithmetic operations will produce results that are reasonably compatible with releases for Compaq COBOL for OpenVMS Alpha prior to Version 2.7 and also with Compaq COBOL for OpenVMS VAX.
STANDARD | Most common arithmetic operations will produce results that are predictable, reasonable, and portable. In this context, portable means that the results will be identical from implementation to implementation. /ARITHMETIC=STANDARD forces /MATH_INTERMEDIATE=CIT4 (described in Section 2.7.2.1).

The default is /ARITHMETIC=NATIVE ( `-arithmetic native` ).

Using the OPTIONS Paragraph (Alpha)

An alternative way to specify native or standard arithmetic is to use the OPTIONS paragraph in the Identification Division of your Compaq COBOL program. There you can specify ARITHMETIC IS NATIVE or STANDARD. Refer to the Compaq COBOL Reference Manual for the syntax and details. <>

## 2.7.3 Specifying a Truncation Qualifier

The `-trunc` flag (on Tru64 UNIX) or the /[NO]TRUNCATE qualifier (on OpenVMS) specifies how the Compaq COBOL compiler stores values in COMPUTATIONAL receiving items.

By default (assuming that the `-trunc` flag is turned off, or /NOTRUNCATE is set), Compaq COBOL truncates values according to the Alpha hardware storage unit (word, longword, or quadword) allocated to the receiving item.

If you specify `-trunc` or /TRUNCATE, the compiler truncates values according to the number of decimal digits specified by the PICTURE clause.

## 2.7.4 Using the ROUNDED Phrase

Rounding is an important option that you can use with arithmetic operations.

You can use the ROUNDED phrase with any Compaq COBOL arithmetic statement. Rounding takes place only when the ROUNDED phrase requests it, and then only if the intermediate result has low-order digits that cannot be stored in the result.

Compaq COBOL rounds off by adding a 5 to the leftmost truncated digit of the absolute value of the intermediate result before it stores that result.

Table 2-4 shows several ROUNDING examples.

Table 2-4 ROUNDING
PICTURE clause |  | Initial Value
--- | --- | ---
03 ITEMA PIC S9(5)V9999. |  | 12345.2222
03 ITEMB PIC S9(5)V99. |  | 54321.11
03 ITEMC PIC S9999. |  | 1234
03 ITEMD PIC S9999P. |  | 0
03 ITEME PIC S99V99 VALUE 9. |  | 9.00
03 ITEMF PIC S99V99 VALUE 24. |  | 24.00
Arithmetic Statement | Intermediate Result | ROUNDED Result Value
ADD ITEMA TO ITEMB ROUNDED. | 066666.3322 | 66666.33
MULTIPLY ITEMC BY 2 GIVING ITEMD ROUNDED. | 02468 | 02470 1
DIVIDE ITEME INTO ITEMF ROUNDED. | 02.666 | 02.67
DIVIDE ITEME INTO ITEMF GIVING ITEMC ROUNDED. | 02.666 | 0003

1The trailing 0 is implied by the P in the PICTURE clause.

### 2.7.4.1 ROUNDED with REMAINDER

The remainder computation uses an intermediate field that is truncated, rather than rounded, when you use the DIVIDE statement with both the ROUNDED and REMAINDER options.

## 2.7.5 Using the SIZE ERROR Phrase

The SIZE ERROR phrase detects the loss of high-order nonzero digits in the results of Compaq COBOL arithmetic operations. It does this by checking the absolute value of an arithmetic result against the PICTURE character-string of each resultant identifier. For example, if the absolute value of the result is 100.05, and the PICTURE character-string of the resultant identifier is 99V99, the SIZE ERROR phrase detects that the high-order digit, 1, will be lost, and the size error condition will be raised.

You can use the phrase in any Compaq COBOL arithmetic statement.

When the execution of a statement with no ON SIZE ERROR phrase results in a size error, and native arithmetic is used, the values of all resultant identifiers are undefined. When standard arithmetic is used, or when the same statement includes an ON SIZE ERROR phrase, receiving items for which the size error exists are left unaltered; the result is stored in those receiving items for which no size error exists. The ON SIZE ERROR imperative phrase is then executed.

If the statement contains both ROUNDED and SIZE ERROR phrases, the result is rounded before a size error check is made.

The SIZE ERROR phrase cannot be used with numeric MOVE statements. Thus, if a program moves a numeric quantity to a smaller numeric item, it can lose high-order digits. For example, consider the following move of an item to a smaller item:

    01 AMOUNT-A PIC S9(8)V99.
    01 AMOUNT-B PIC S9(4)V99.
           .
           .
           .
           MOVE AMOUNT-A TO AMOUNT-B.

This MOVE operation always loses four of AMOUNT-A's high-order digits. The statement can be tailored in one of three ways, as shown in the following example, to determine whether these digits are zero or nonzero:

    1.  IF AMOUNT-A NOT > 9999.99
           MOVE AMOUNT-A TO AMOUNT-B
           ELSE ...
    2.  ADD ZERO AMOUNT-A GIVING AMOUNT-B
           ON SIZE ERROR ...
    3.  COMPUTE AMOUNT-B = AMOUNT-A
           ON SIZE ERROR ...

All three alternatives allow the MOVE operation to occur only if AMOUNT-A loses no significant digits. If the value in AMOUNT-A is too large, all three avoid altering AMOUNT-B and take the alternate execution path.

You can also use a NOT ON SIZE ERROR phrase to branch to, or perform, sections of code only when no size error occurs.

## 2.7.6 Using the GIVING Phrase

The GIVING phrase moves the intermediate result of an arithmetic operation to a receiving item. The phrase acts exactly like a MOVE statement in which the intermediate result serves as the sending item, and the data item following the word GIVING serves as the receiving item. When a statement contains a GIVING phrase, you can have a numeric-edited receiving item.

The receiving item can also have the ROUNDED phrase. If the receiving item is also numeric-edited, rounding takes place before the editing.

The GIVING phrase can be used with the ADD, SUBTRACT, MULTIPLY, and DIVIDE statements. For example:

    ADD A,B GIVING C.

## 2.7.7 Multiple Operands in ADD and SUBTRACT Statements

Both the ADD and SUBTRACT statements can contain a series of operands preceding the word TO, FROM, or GIVING.

If there are multiple operands in either of these statements, the operands are added together. The intermediate result of that operation becomes a single operand to be added to or subtracted from the receiving item. In the following examples, TEMP is an intermediate result item:

1. | Statement: | ADD A,B,C,D, TO E,F,G,H.
| Equivalent coding: | ADD A, B, GIVING TEMP. ADD TEMP, C, GIVING TEMP. ADD TEMP, D, GIVING TEMP. ADD TEMP, E, GIVING E. ADD TEMP, F, GIVING F. ADD TEMP, G, GIVING G. ADD TEMP, H, GIVING H.
2. | Statement: | SUBTRACT A, B, C, FROM D.
| Equivalent coding: | ADD A, B, GIVING TEMP. ADD TEMP, C, GIVING TEMP. SUBTRACT TEMP FROM D, GIVING D.
3. | Statement: | ADD A,B,C,D, GIVING E.
| Equivalent coding: | ADD A,B, GIVING TEMP. ADD TEMP, C, GIVING TEMP. ADD TEMP, D, GIVING E.

As in all Compaq COBOL statements, the commas in these statements are optional.

## 2.7.8 Common Errors in Arithmetic Statements

Programmers most commonly make the following errors when using arithmetic statements:

- Using an alphanumeric item in an arithmetic statement. The MOVE statement allows data movement between alphanumeric items and certain numeric items, but arithmetic statements require that all items be numeric.
- Writing the ADD or SUBTRACT statements without the GIVING phrase, and attempting to put the result into a numeric-edited item.
- Subtracting a 1 from a numeric counter that was described as an unsigned quantity and then testing for a value less than zero.
- Forgetting that the MULTIPLY statement, without the GIVING phrase, stores the result back into the second operand (multiplier).
- Performing a series of calculations that generates an intermediate result larger than 18 digits when the final result will have 18 or fewer digits. You can prevent this problem by interspersing divisions with multiplications or by dropping nonsignificant digits after multiplying large numbers or numbers with many decimal places. Also, avoid use of the COMPUTE statement to keep from performing such calculations implicitly.
- Forgetting that when an arithmetic statement has multiple receiving items you must specify the ROUNDED phrase for each receiving item you want rounded.
- Forgetting that the ON SIZE ERROR phrase applies to all receiving items in an arithmetic statement containing multiple receiving items. Only those receiving items for which a size error condition is raised are left unaltered. The ON SIZE ERROR imperative statement is executed after all the receiving items are processed.
- Controlling a loop by adding to a numeric counter that was described as PIC 9, and then testing for a value of 10 or greater to exit the loop.
- Forgetting that ROUNDING is done before the ON SIZE ERROR test.

Previous | Next | Contents | Index