MULTIPLY and DIVIDE
MULTIPLY and DIVIDE follow the same pattern as ADD and SUBTRACT:
without GIVING, the last field named is overwritten with the result; with
GIVING, only the GIVING field changes.
MULTIPLY ... BY
MULTIPLY 3 BY WS-QTY
MULTIPLY WS-QTY BY WS-PRICE GIVING WS-LINE-TOTAL
The first statement triples WS-QTY — the field after BY receives the
product. That means MULTIPLY WS-QTY BY 3 (a literal after BY, no
GIVING) is a compile error: you can't store an answer in a literal.
DIVIDE ... INTO and DIVIDE ... BY
DIVIDE has two word orders, and they read in opposite directions:
| Statement | Meaning |
|---|---|
DIVIDE 4 INTO WS-A |
WS-A = WS-A / 4 |
DIVIDE 4 INTO 20 GIVING WS-Q |
WS-Q = 20 / 4 |
DIVIDE 20 BY 4 GIVING WS-Q |
WS-Q = 20 / 4 |
INTO puts the divisor first ("4 goes into 20"). BY puts the dividend
first ("20 divided by 4"). BY is only allowed with GIVING.
REMAINDER
Integer division with a remainder is how COBOL answers questions like "how many full boxes, and how many loose items?":
IDENTIFICATION DIVISION.
PROGRAM-ID. BOXES.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 WS-Q PIC 9(3).
01 WS-R PIC 9(3).
01 WS-A PIC 9(3) VALUE 30.
01 WS-P PIC 9(3)V99.
PROCEDURE DIVISION.
DIVIDE 17 BY 5 GIVING WS-Q REMAINDER WS-R
DISPLAY "17 / 5 = " WS-Q " REMAINDER " WS-R
DIVIDE 4 INTO WS-A
DISPLAY "30 / 4 = " WS-A
DIVIDE 4 INTO 30 GIVING WS-P
DISPLAY "30 / 4 = " WS-P
STOP RUN.
Output:
17 / 5 = 003 REMAINDER 002
30 / 4 = 007
30 / 4 = 007.50
Look at the middle line. 30 / 4 is 7.5, but WS-A has no decimal places,
so the .5 is simply dropped. COBOL truncates by default — it does not
round, and it gives no warning. Give the receiving field enough decimal
places (V99) and you get 7.50.
Truncation is silent
Excess decimal digits are cut off, and so are excess leading digits (unless you ask to be told — see the size error lesson). Always check that the receiving picture is big enough in both directions.
Why not just use /?
You can (COMPUTE is two lessons away). But you will spend much of your
career reading code written in the verb style, especially older programs,
and DIVIDE ... REMAINDER has no one-symbol equivalent.
On the job
DIVIDE ... REMAINDER turns up in date logic (days into weeks), check
digits and paging ("which page does line 137 fall on?"). When you see
INTO, say it out loud as "goes into" and you'll never read it backwards.
Your task
A warehouse program reads three values, one per line:
- the number of items to ship (whole number, up to 5 digits)
- how many items fit in a box (whole number, up to 3 digits, never zero)
- the weight of one item in kg, with two decimals (e.g.
1.25)
Display the number of full boxes, the number of loose items left over, and the total weight of all items:
FULL BOXES: 00012
LOOSE ITEMS: 004
TOTAL WEIGHT: 000155.00
(That's the output for 124, 10, 1.25.) Use DIVIDE ... GIVING ...
REMAINDER and MULTIPLY ... GIVING. The fields you need are declared.