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 ADD-ANS-OUT PIC Z,ZZ9.99. 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):
ADD FIRST-NUMBER TO SECOND-NUMBER GIVING ADD-ANS-WS. ADD FIRST-NUMBER SECOND-NUMBER GIVING ADD-ANS-WS. ADD FIRST-NUMBER, SECOND-NUMBER GIVING ADD-ANS-WS. ADD 12 TO FIRST-NUMBER GIVING ADD-ANS-WS. ADD 100, FIRST-NUMBER, SECOND-NUMBER GIVING ADD-ANS-WS.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).
ADD 50 TO FIRST-NUMBER. ADD FIRST-NUMBER TO SECOND-NUMBER.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.
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:
ADD FIRST-NUMBER TO SECOND-NUMBER GIVING ADD-ANS-WHOLE-WS ROUNDED.
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.
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.
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.
SUBTRACT FIRST-NUMBER FROM SECOND-NUMBER GIVING WHOLE-ANS-WS ROUNDED.
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 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!
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 {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 {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 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.
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.
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.
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.
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.