A fee-calculator program that loops, over-counts and divides by zero
A coaching centre in Rohtak asks a Class XII IT student to write a Python program that reads the number of students n, then for each student reads a name and marks, computes a fee of rupees 1,200 per subject for three subjects with a 15 per cent concession if marks are 90 or above, prints a receipt per student, and finally prints the class average. The submitted program loops forever on some inputs; it prints 31 receipts when 30 students are entered; one student with exactly 90 marks got the concession in one test run and not in another because the condition was written as marks > 90 in one place and marks >= 90 in another; the grand total is reset to zero inside the loop, so it always equals the last student's fee; and the program crashes with ZeroDivisionError when n is entered as 0. The same logic is also required in Java for the practical file.
1. Rewrite the design so the average can be computed and the Java version behaves identically, and name the traps that typically make the two versions disagree.
Read the worked answer
Structure both versions the same way so they can be compared line by line:
- Read n, validate n > 0 before any division.
- Initialise total_fee and total_marks to 0 before the loop.
- Loop exactly n times.
- Inside: read name and marks; base = 3 * 1200; if marks >= 90 apply a 15 per cent concession, i.e. fee = base * 0.85; else fee = base; add to totals; print the receipt.
- After the loop: class average = total_marks / n.
Java traps that cause divergence:
- Integer division. total_marks / n with both ints truncates, so 227/3 gives 75 in Java but 75.67 in Python 3. Cast: (double) total_marks / n.
- Input handling. Java needs Scanner and nextInt()/nextLine() together; a leftover newline after nextInt() makes nextLine() read an empty name. Python's input() has no such issue.
- Money precision. Doubles are fine for a school exercise, but state explicitly that the result is rounded to two places before printing, or the two versions print different values for the same input.
- Off-by-one. Java for (int i = 0; i < n; i++) and Python range(n) mean the same thing; range(n + 1) does not.
2. Produce a dry run with three students - marks 92, 90 and 45 - and use it to show that the fixes work, including the n = 0 path.
Read the worked answer
Base fee per student = 3 subjects x 1200 = 3600. Concession rule: marks >= 90 gives 15 per cent off, i.e. fee = 3600 x 0.85 = 3060; otherwise 3600.
| Student | Marks | Condition | Fee | Running total_fee |
|---|---|---|---|---|
| 1 | 92 | 92 >= 90 true | 3060 | 3060 |
| 2 | 90 | 90 >= 90 true | 3060 | 6120 |
| 3 | 45 | 45 >= 90 false | 3600 | 9720 |
What the table proves:
- The loop iterates exactly 3 times, so 3 receipts print, not 4.
- Student 2 with exactly 90 marks gets the concession, confirming the >= rule is applied consistently; under the old > 90 code the fee would have been 3600, and the table would have shown 6660 total instead of 6120 at that row - a visible, checkable difference.
- The total is 9720, not 3600, proving initialisation was moved outside the loop.
Average marks = (92 + 90 + 45) / 3 = 227 / 3 = 75.67 in Python 3; in Java the same expression with int operands returns 75, so the cast to double is required for identical output.
n = 0 path: the guard rejects the input and prints 'no students to process', so the division is never reached and ZeroDivisionError cannot occur. Test both n = 0 and n = -1, since only the positive case was considered originally.