Beginner project · Small
Bill splitter and tip calculator
Your program reads a bill total, a number of people and a tip percentage, then prints the tip, the new total and what each person owes. The interesting part is the last cent: a total that does not divide evenly has to be shared out so the parts still add up to the total exactly. That single requirement turns a two-line calculation into a real little program.
- Languages
- JavaScript
- Size
- Small: one sitting for most learners
- Where to build it
- Runs as-is in the JavaScript playground: readline() takes the next line from the input box, so put your three values on three lines. Open the JavaScript playground →
What you will practise
- reading several values from input and validating each one
- avoiding floating-point money bugs by working in whole cents
- integer division and the remainder operator
- formatting numbers for display with a fixed number of decimals
- writing small functions that each do one job
Requirements
The project is done when every one of these is true.
- The program reads three values, one per line, in this order: the bill total in currency units, the number of people as a whole number, and the tip percentage as a number.
- All money arithmetic happens in whole cents held as integers; no intermediate value is a fractional number of cents.
- The output shows the bill, the tip amount, the total with tip, and the amount each person owes, each printed with exactly two decimal places.
- The individual amounts add up to the total with tip exactly, to the cent, with no rounding gap.
- When the total does not divide evenly, the extra cents are given to the first few people, one cent each, and the output makes clear that not everyone pays the same.
- A number of people below 1 prints a clear message and no split, instead of dividing by zero.
- A negative bill total or a negative tip percentage prints a clear message and no split.
- A tip percentage of 0 is accepted and produces a tip of 0.00, not an error.
Milestones
A sensible order to build it in, so something works at every step.
Read and echo the three values
Read three lines, convert them, and print them straight back out so you can see the parsing is right before any arithmetic exists.
Convert the bill to whole cents
Turn the bill into an integer number of cents and write a small function that turns cents back into a two-decimal string, so display and arithmetic never mix.
Calculate the tip and the new total in cents
Compute the tip from the cent total and the percentage, round it to a whole number of cents, and add it on.
Split evenly and find the remainder
Use integer division for the base share and the remainder operator for the leftover cents, then check the two numbers reconstruct the total.
Hand out the leftover cents
Build a list of per-person amounts where the first few people get one extra cent each, then print it with a line explaining the difference.
Add the validation messages
Reject fewer than one person and negative amounts with their own messages, and make sure each rejection stops before the split is printed.
Hints
Open one only when you are stuck. Each gives a little more away.
Show hint 1Hint 1
0.1 + 0.2 is not exactly 0.3 in floating point, which is why money in cents as integers is not fussiness but a bug fix. Convert once at the start and once at the end.
Show hint 2Hint 2
Converting a bill to cents with a multiplication can still land just under a whole number. Round the result to the nearest integer rather than truncating it.
Show hint 3Hint 3
Integer division gives the base share and the remainder operator gives exactly how many people need one extra cent. Those two numbers are all you need, and you never have to loop to find them.
Show hint 4Hint 4
Prove the split before you print it: add the per-person amounts back up and compare with the total. If they differ, the bug is in the split, not in the formatting.
Show hint 5Hint 5
A two-decimal string from an integer number of cents does not need a rounding function at all: the whole part and the last two digits are already there.
How to test it
Run these checks yourself, or turn them into automated tests once you know how.
- Feed 84.50, 4, 18. The tip is 15.21, the total with tip is 99.71, and the split is three people at 24.93 and one at 24.92, which sums back to 99.71.
- Feed 30, 3, 0. The tip is 0.00, the total is 30.00 and each person owes exactly 10.00.
- Feed 100, 3, 10. The tip is 10.00, the total is 110.00, and the split is two people at 36.67 and one at 36.66, summing to 110.00.
- Feed 20, 1, 15. One person owes the whole 23.00, and no remainder line is needed.
- Feed 10, 0, 10. Expect a message about needing at least one person, and no division.
- Feed -5, 2, 10. Expect a message about the bill needing to be zero or more, and no split.
- For any input you try, add the printed per-person amounts together on paper and check they match the printed total exactly.
- Feed 0, 4, 20. Everyone owes 0.00, which catches code that assumes the total is always positive.
Stretch goals
- Add a fourth input line for people who are not tipping, and split only the tip among the rest.
- Accept a per-person weight list so that someone who ordered more pays a larger share, while the parts still sum to the total.
- Print a rounded-up total per person as an alternative, and show how much extra tip that leaves.
- Add a mode that takes a target total per person and tells you what tip percentage gets closest to it.