Mathematical Calculations

Doing calculations is basic to computer programming. COBOL provides all of the calculation power that is needed for most business programming. It is not the appropriate language to use if you want to do high power mathematics.

The ADD statement has two purposes: the first is to do a simple calculation that adds one or more numbers together and produces an answer, the second is adding one number to another and storing the answer in the second number. A frequent application of this is adding to accumulate a total. Only the simple version is covered here, other clauses are available and will be covered separately. First, we will look at the ADD to do a simple calculation. To illustrate, I will use the WORKING-STORAGE SECTION from the program ADDDA4.CBL.

WORKING-STORAGE SECTION.
01  INPUT-AREA.
05  GET-ACCEPT-ANS           PIC X          VALUE SPACES.
05  FIRST-NUMBER             PIC 999V99     VALUE 0.
05  SECOND-NUMBER            PIC 999V99     VALUE 0.
01  WORK-AREA.
05  ADD-ANS-WS               PIC 9999V99    VALUE 0.
05  FINAL-ANS-WS             PIC 9999V99    VALUE 0.
01  OUTPUT-AREA.
05  FINAL-ANS-OUT            PIC Z,ZZ9.99.
Sample basic ADD statements (Note that these would be located in a paragraph in the PROCEDURE DIVISION):
The ADD statement can also be used to add the contents of one field to another or add a literal to a field. Note that you cannot add to a literal, only to a defined field (identifier).
In the first example, since there is no GIVING clause in this statement, FIRST-NUMBER would be increased by 50. The original value in FIRST-NUMBER would be lost. In the second example SECOND-NUMBER would increase by the contents of FIRST-NUMBER and the original value in SECOND-NUMBER would be lost.
You can also round the answer by using the ROUNDED CLAUSE. For example, this would be necessary if you were adding two decimal numbers and storing the answer as a whole number.
WORKING-STORAGE SECTION.
01  INPUT-AREA.
05  GET-ACCEPT-ANS           PIC X          VALUE SPACES.
05  FIRST-NUMBER             PIC 999V99     VALUE 0.
05  SECOND-NUMBER            PIC 999V99     VALUE 0.
01  WORK-AREA.
05  ADD-ANS-WHOLE-WS         PIC 9999       VALUE 0.

In the PROCEDURE DIVISION:

In this example the numbers would be added together and the decimals would be lost when the answer was stored. If the calculation did not have ROUNDED, the decimals would be truncated. With the ROUNDED clause the answer would be ROUNDED following the standard rules of rounding. For example: assume that FIRST-NUMBER is 12.75 and second number is 3.07. When they are added together I get 15.82. Since I cannot store the .82, the number will be truncated if there is no ROUNDED clause and you will see 15. If there is a rounded clause, the number will be ROUNDED and you will see 16.

Format of simple calculation using the ADD statement:

ADD {literal-1 or identifier-1} ... literal-n or identifier-n
GIVING identifier-x [ROUNDED].

ADD{literal-1 or identifier-1}... TO literal-n or identifier-n
GIVING identifier-x [ROUNDED].

The ADD statement lets you add literals (actual number) and/or identifiers (contents of fields - can be defined in the File Section or the Working-Storage Section) and store the answer in an identifer (usually defined in Working-Storage). The word TO is optional - in versions of COBOL before COBOL '85 you could not use TO and GIVING in the same ADD statement. The GIVING clauses points to the place where the answer will be stored (identifier-x). When an ADD is done, any previous value that is stored in identifier-x will be wiped out and replaced with the result of the calculation. ROUNDED is optional. If the clause ROUNDED is used, the answer will be rounded to fit the identifier defined as the answer. If ROUNDED is not used, the answer will be truncated to fit the identifier defined as the answer.

SUBTRACT:

Like the ADD, the SUBTRACT can be used to do a subtraction and arrive at an answer (using the GIVING clause)or it can be used to decrease a specified field and put the answer back in the field (using the FROM clause without the GIVING clause). Again, the ROUNDED clause is optional and can be used to round the answer to fit the field as opposed to the default which truncates the answer to fit the field. Other options will be discussed later.

WORKING-STORAGE SECTION.
01  INPUT-AREA.
05  GET-ACCEPT-ANS           PIC X          VALUE SPACES.
05  FIRST-NUMBER             PIC 999V99     VALUE 0.
05  SECOND-NUMBER            PIC 999V99     VALUE 0.
01  WORK-AREA.
05  ANS-WS                   PIC 9999V99    VALUE 0.
05  FINAL-ANS-WS             PIC 9999V99    VALUE 0.
01  OUTPUT-AREA.
05  ANS-OUT                  PIC Z,ZZ9.99.
05  FINAL-ANS-OUT            PIC Z,ZZ9.99.
Examples of the subtract statement:
SUBTRACT FIRST-NUMBER FROM SECOND-NUMBER
GIVING ANS-WS.
SUBTRACT 10 FROM SECOND-NUMBER
GIVING ANS-WS.
SUBTRACT FIRST-NUMBER FROM 100
GIVING ANS-WS.
If you do not use the giving clause, then the answer is stored in the field after the FROM. Note that the field after the from must be an identifier/field name, it cannot be a literal. In other words you have to store it in something that has been defined in memory.
SUBTRACT 10 FROM SECOND-NUMBER.
SUBTRACT FIRST-NUMBER FROM SECOND-NUMBER.
In both examples, SECOND-NUMBER would be decreased from its original value.

You can also use rounded with the subtract statement. Assume that WHOLE-ANS-WS has a PIC 9999. Without the ROUNDED clause, the results would be truncated to fit the field. With the ROUNDED clause, the results will be rounded using the normal rules for rounding.
SUBTRACT FIRST-NUMBER FROM SECOND-NUMBER
GIVING WHOLE-ANS-WS ROUNDED.

FORMAT OF SIMPLE SUBTRACT CALCULATION:

SUBTRACT {literal-1 or identifier-1} ... FROM identifier-n
GIVING identifier-x [ROUNDED].
NEGATIVE NUMBERS: Note that we have not dealt with negative numbers yet, you must test these subtractions with that in mind. In other words, you should use numbers so the answers will always be positive.

MULTIPLY:

The MULTIPLY statement again has two purposes, each with its own format. The MULTIPLY statement can be used to multiply two literals or identifiers together and store the results in an answer field (defined by the GIVING clause) where the old answer is wiped out and replaced with the new answer. In this case, if there are identifiers other than the answer involved in the MULTIPLY they are not effected, their contents remains the same. The MULTIPLY statement can also be used to multiply a literal or identifier by an identifier and store the answer back in the identifier replacing the value that used to be there. In this format, there is no GIVING clause. Either format supports the optional ROUNDED clause that causes the answer to be rounded rather than truncated. Other options are available and will be discussed later. When you are doing multiplication, the size of the answer is determined by the size of the fields used in the calculation. Essentially if you add the number of whole number digits in each of the fields in the calculation, the sum should be the number of whole number digits that you setup in the answer field.

Examples of the multiply statement:
MULTIPLY FIRST-NUMBER BY SECOND-NUMBER
GIVING ANS-WS.
MULTIPLY 12 BY SECOND-NUMBER
GIVING ANS-WS.
MULTIPLY FIRST-NUMBER BY 12
GIVING ANS-WS.
MULTIPLY FIRST-NUMBER BY SECOND-NUMBER
GIVING WHOLE-ANS-WS ROUNDED.
Note that you have to figure out the size of the answer field a little differently when you are doing a multiply. If you are multiplying 2 digits by 3 digits, you need a 5 digit answer (for example: 90 times 900 = 81000). If you are multiplying 3 digits by 4 digits, you need a 7 digit answer. In other words add up the digits being multiplied and that is the size of the answer. Try it!

If you do not use the GIVING clause, the answer gets stored in the field after the B. Note that you must have an identifier after the BY, not a literal when you do not have the GIVING clause.
MULTIPLY FIRST-NUMBER BY SECOND-NUMBER.
In this example, the results will be stored in SECOND-NUMBER, wiping out the previous data that was stored there!

MULTIPLY USING THE GIVING CLAUSE:

MULTIPLY {identifier-1 or literal-1} BY {identifier-2 or literal-2}
GIVING identifer-x [ROUNDED].
The MULTIPLY statement multiplies either a literal or an identifier by another literal or identifier and stores the answer in an identifier setup to hold the answer. The fields involved in the calculation retain their original values, the answer identifier receives the result of the calculation as its value wiping out any previous value in the field.

MULTIPLY USING THE BY CLAUSE WITHOUT THE GIVING CLAUSE:

MULTIPLY {identifier-1 or literal-1} BY identifier-x [ROUNDED].
The MULTIPLY statement multiplies an identifer or literal by an identifer and stores the answer back in that identifier. The original value of the answer identifier is lost.

DIVIDE:

The DIVIDE has 5 different options. Not only is there the option to use or omit the GIVING clauses, but there is also the option to use either BY or INTO in the DIVIDE itself.

Examples of the DIVIDE with the INTO:
DIVIDE 10 INTO FIRST-NUMBER
GIVING ANS-WS.
DIVIDE FIRST-NUMBER INTO SECOND-NUMBER
GIVING ANS-WS.
DIVIDE FIRST-NUMBER INTO SECOND-NUMBER
GIVING WHOLE-ANS-WS ROUNDED.
In the first example, 10 is divided into FIRST-NUMBER and the result is put into ANS-WS. IF FIRST-NUMBER is 50, then 10 is divided into 50 and the result of 5 is put into ANS-WS. In the second and third examples the contents of FIRST-NUMBER is divided into the contents of SECOND-NUMBER and the results are put into the identifier after the GIVING. In the third example, the answer is rounded before it is stored in WHOLE-ANS-WS.

Examples of the DIVIDE with the BY:
DIVIDE FIRST-NUMBER BY 10
GIVING ANS-WS.
DIVIDE SECOND-NUMBER BY FIRST-NUMBER
GIVING ANS-WS.
DIVIDE SECOND-NUMBER BY FIRST-NUMBER
GIVING WHOLE-ANS-WS ROUNDED.
I did the same mathematical problems in these 3 examples as I did in the original examples. Looking at the first example, if FIRST-NUMBER contains a 50 then 50 will be divided by 10 and the result of 5 will be put into ANS-WS.

Note that only the INTO can be used if there is no GIVING clause.
DIVIDE 10 INTO FIRST-NUMBER.
DIVIDE FIRST-NUMBER INTO SECOND-NUMBER.
DIVIDE FIRST-NUMBER INTO SECOND-NUMBER ROUNDED.
In all of these examples, the contents of the identifier after the INTO is changed and the previous content is wiped out.

The DIVIDE also allows the programmer to store the remainder. Note that you cannot use ROUNDED when you are storing the remainder. THis can be done with either the BY or INTO. Assume in these examples that I have defined a field in working storage called REM-WS.
DIVIDE 10 INTO FIRST-NUMBER
GIVING ANS-WS REMAINDER REM-WS.
DIVIDE FIRST-NUMBER INTO SECOND-NUMBER
GIVING ANS-WS REMAINDER REM-WS.
DIVIDE FIRST-NUMBER BY 10
GIVING ANS-WS REMAINDER REM-WS.
DIVIDE SECOND-NUMBER BY FIRST-NUMBER
GIVING ANS-WS REMAINDER REM-WS.

DIVIDE FORMATS:

1.	DIVIDE {literal-1 or identifier-1} INTO {literal-2 or identifier-2}
GIVING identifier-x [ROUNDED].

2.	DIVIDE {literal-1 or identifier-1} INTO {literal-2 or identifier-2}
GIVING identifier-x [ROUNDED] REMAINDER indentifier-r.

3.	DIVIDE {literal-1 or identifier-1} INTO identifier-2 [ROUNDED].

4.	DIVIDE {literal-1 or identifier-1} BY {literal-2 or identifier-2}
GIVING identifier-x [ROUNDED].

5.	DIVIDE {literal-1 or identifier-1} BY {literal-2 or identifier-2}
GIVING identifier-x [ROUNDED] REMAINDER indentifier-r.