COBOL GnuCOBOL 3.2.0 ยท
โ verified by execution on 2026-08-16
You have learned how to define data, calculate mathematics, make logical decisions, and format output. Now it is time to bring these foundations together.
In this capstone project, we will build a batch COBOL program that processes a simple payslip. It will take raw hours and rate, calculate overtime and taxes, and finally generate a formatted receipt.
The Architecture
A well-structured COBOL program isolates its tasks. Instead of writing one massive block of code, we use PERFORM to delegate work to specific paragraphs.
In 100-MAIN, we simply delegate tasks using PERFORM. It reads like an outline of the program.
Why COBOL Uses Global State
A modern programmer reading this architecture would immediately expect to pass parameters, like PERFORM 200-CALCULATE-PAY(HOURS, RATE). That intuition fails in COBOL because paragraphs are not functions. They have no parameters and no local scope. Everything defined in WORKING-STORAGE is perfectly global to the entire program.
Why did the language designers build it this way? In the mainframe era, allocating and deallocating memory on a call stack for millions of payroll records was unacceptably slow. By making all memory global and static, COBOL programs run at blistering speeds because memory addresses are resolved completely at compile time, eliminating runtime memory management.
The boundary where this rule stops applying is recursion. Because there is no call stack and no local variables, a standard COBOL paragraph cannot safely call itself without overwriting its own data. This is why COBOL is unmatched for flat batch processing, but completely unsuitable for recursive algorithms like walking tree data structures.
The Pitfall of Raw Data
A common misconception is trying to display computational fields directly. Because COBOL uses implied decimals (V) for math to ensure precision without wasting memory on the decimal character, you cannot print them directly if you want human readability.
Predict the outputcobol
What gets displayed if we print the raw computational field?
IDENTIFICATION DIVISION. PROGRAM-ID. RAW-PRINT. DATA DIVISION. WORKING-STORAGE SECTION. 01 RAW-PAY PIC 9(4)V99 VALUE 1500.50. PROCEDURE DIVISION. DISPLAY RAW-PAY. STOP RUN.
Output
1500.50
You predicted
Without moving RAW-PAY to an edited picture like PIC $$$,$$9.99, COBOL dumps the memory contents unformatted, omitting commas and dollar signs, but GnuCOBOL retains the implied decimal in its display output.
The Complete Payslip Calculator
Here is the final, assembled project. We define our raw fields, calculated buffers, and edited print formats. Then, we execute the business logic and move the results to the display buffer.
============================
PAYSLIP REPORT
============================
EMPLOYEE: JANE DOE
GROSS PAY: $950.00
TAX DEDUCT: $190.00
NET PAY: $760.00
============================
Your output
Try it yourself
Now it is your turn to modify the project components.
Congratulations on building your first substantial COBOL application! You now possess the foundational knowledge to read and trace standard batch COBOL programs.
Check yourself
Why do we move computational fields with implied decimals (like `PIC 9(5)V99`) to edited picture fields before displaying them?
Reveal answer
Because computational fields will print as raw digits without the decimal point, making them hard for humans to read. โ Computational fields with implied decimals (`V`) will print exactly as raw digits without the decimal point. You must MOVE them to an edited picture field (like `PIC $$$,$$9.99`) before displaying to add commas, dollar signs, and decimal points.
How does the PROCEDURE DIVISION handle execution flow by default?
Reveal answer
It executes top to bottom and can fall through into other paragraphs unless explicitly stopped. โ While it can fall through, the standard COBOL design pattern uses a main driver paragraph (like `100-MAIN`) that `PERFORM`s other paragraphs and then ends with `STOP RUN`, preventing accidental fall-through.
What happens if an edited picture is not large enough to hold the output, such as moving 1000 into PIC $9.99?
Reveal answer
The value will be truncated and only the rightmost digits will fit. โ COBOL truncates data if the destination variable is too small. You must ensure your edited picture has enough digit places (9s or Zs) to hold the maximum expected value.
Challenges
Challenge 1 +25 XP
Update the tax calculation so that any `GROSS-PAY` over 1000 is taxed at 25%, and everything else is taxed at 10%.
cobolโ solution verified at build time
COBOL has no in-browser runtime, so this one is pen-and-paper: work out what the
fixed code should be, then open the solution and compare. The expected output
below is real โ it came from compiling the solution with GnuCOBOL when this page
was built.
Test 1 โ expects "TAX: $300.00\n"
Need a hint? (โ25% XP)
Change the condition to check if GROSS-PAY > 1000, and multiply by 0.25.
The `NET-PAY` below has an implied decimal. Define `PRT-NET` with an edited picture that displays it as a floating dollar amount with commas (e.g. $1,550.50).
cobolโ solution verified at build time
COBOL has no in-browser runtime, so this one is pen-and-paper: work out what the
fixed code should be, then open the solution and compare. The expected output
below is real โ it came from compiling the solution with GnuCOBOL when this page
was built.