hands-on labIDE in your browserfree

The Receipt: Money in Whole Pennies

Make Bean There's till print a receipt Sam can hand over without checking it: prices in whole pennies, pounds and pence with // and %, the zero in £3.05, and columns that line up, one idea per step.

time
30 min
checked steps
5
level
Beginner
setup
None

Freeone of 170+ labs in Pro

free · no account needed to start

The job

Sam's old till printed £9.600000000000001 for three flat whites, and customers noticed. Your job this morning: a till that keeps money exact and prints a receipt that looks like a receipt, with the pounds and pence right and the amounts lined up in a column.

5 steps, each checked when you finish it

A check runs your work at the end of every step. Hints and the full solution are there if you get stuck.

  1. 1

    Money in whole pennies

    Sam typed this into the old till for three flat whites at £3.20:

    read this step below ↓

  2. 2

    Pounds and pence with // and %

    How many whole pounds are in 885 pennies, and how many pennies are left over?

  3. 3

    The £ sign, and the zero that goes missing

    Priya came back to the counter holding her receipt.

  4. 4

    Line up the columns

    Two receipts for the same order.

  5. 5

    The whole receipt

    Sam tears a strip off the receipt roll to show you how a Bean There receipt starts and ends:

The lab, step by step

The free lab’s own text, every step of it. Hints and solutions stay inside the lab.

Step 1: Money in whole pennies

Sam typed this into the old till for three flat whites at £3.20:

print(3.20 * 3)

and the till answered:

9.600000000000001

A number with a decimal point is a float, and Python keeps floats in binary. Most decimals, 3.20 among them, have no exact binary form, so a sum can come out a hair off. Shops won't have that, so tills count whole pennies instead: £3.20 is 320. Whole numbers (integers) are always exact.

receipt.py keeps its prices that way:

FLAT_WHITE = 320
CROISSANT = 245

The capitals are a habit, not a rule: programmers write a value the script never changes, like a price, in capitals so it stands out. Sam's order sits underneath, flat_whites = 2 and croissants = 1.

Work out the order's total in pennies, keep it in a variable called total (the next steps use it) and print it:

Total in pennies: 885

* multiplies and + adds, and Python does the multiplying first, the way arithmetic always works. Press Run, then Check. The check changes the order and the prices and runs receipt.py again, so the total has to come from the variables.

receipt.py, the file you edit11 lines
# Bean There's till. Prices are in whole pennies: 320 means £3.20.
FLAT_WHITE = 320
CROISSANT = 245

# Sam's order
flat_whites = 2
croissants = 1

# TODO (Step 1): work out the order's total in pennies, keep it in a variable called total,
# and print it:
#   Total in pennies: 885

Step 2: Pounds and pence with // and %

How many whole pounds are in 885 pennies, and how many pennies are left over? You'd say 8 and 85 without thinking. Python has an operator for each half:

print(885 // 100)   # 8: how many whole hundreds fit in 885
print(885 % 100)    # 85: what's left over

// is floor division: it divides and throws away anything after the point. % is the remainder (programmers say "modulo"): what's left when the hundreds are taken out. Plain / would give 8.85, a float again.

Keep the total line, and under it print the same total in pounds and pence:

Total in pennies: 885
That's 8 pounds and 85 pence

print takes as many pieces as you like, separated by commas, and puts a space between them, so the words and the two numbers can go in one print. Use // and % on total; the check tries other orders, so typing 8 and 85 won't pass.

receipt.py, the file you edit13 lines
# Bean There's till. Prices are in whole pennies: 320 means £3.20.
FLAT_WHITE = 320
CROISSANT = 245

# Sam's order
flat_whites = 2
croissants = 1

total = flat_whites * FLAT_WHITE + croissants * CROISSANT
print("Total in pennies:", total)

# TODO (Step 2): under it, print the total in pounds and pence, using // and % on total:
#   That's 8 pounds and 85 pence

Step 3: The £ sign, and the zero that goes missing

Priya came back to the counter holding her receipt. One flat white at the new price, 305 pennies, and the till had printed £3.5. Had she been charged three pounds fifty?

Here's what the till did:

total = 305
print(f"Total: £{total // 100}.{total % 100}")    # Total: £3.5

305 % 100 is 5, and Python prints 5 as 5. A price needs two digits after the point, so the fix is a format code after a colon inside the braces:

print(f"Total: £{total // 100}.{total % 100:02d}")    # Total: £3.05

Read :02d from the right: d means a whole number, 2 means at least two characters wide, and 0 means fill the gap with zeros. 5 becomes 05; 85 stays 85.

Replace both print lines with the one line a till prints:

Total: £8.85

The check serves Priya too, so the zero has to be there.

You might know another way: f"£{total / 100:.2f}" divides back to a float and rounds it to two places, and for one total it prints the same thing. Tills keep whole pennies until the very last moment so nothing can drift, which is why this course uses //, % and :02d.

receipt.py, the file you edit14 lines
# Bean There's till. Prices are in whole pennies: 320 means £3.20.
FLAT_WHITE = 320
CROISSANT = 245

# Sam's order
flat_whites = 2
croissants = 1

total = flat_whites * FLAT_WHITE + croissants * CROISSANT
print("Total in pennies:", total)
print("That's", total // 100, "pounds and", total % 100, "pence")

# TODO (Step 3): replace both prints above with the till's line, the pence always two digits:
#   Total: £8.85

Step 4: Line up the columns

Two receipts for the same order. Which would you hand to a customer?

2 x Flat white £6.40
1 x Croissant £2.45
Total £8.85
2 x Flat white        £6.40
1 x Croissant         £2.45
Total                 £8.85

The second one pads every description to the same width so the amounts form a column. Format codes do the padding:

print(f"{'Total':<20}{'£8.85':>7}")

:<20 makes the text 20 characters wide with the text on the left, spaces filling the rest. :>7 makes it 7 wide with the text pushed to the right. A dot marks each space here:

Total···············
··£8.85

Replace the total line with the three receipt lines:

2 x Flat white        £6.40
1 x Croissant         £2.45
Total                 £8.85

Every amount comes from pennies: the flat whites cost flat_whites * FLAT_WHITE, and so on. It helps to build each line's two halves first, then print them together:

flat_white_pennies = flat_whites * FLAT_WHITE
flat_white_line = f"{flat_whites} x Flat white"
flat_white_amount = f"£{flat_white_pennies // 100}.{flat_white_pennies % 100:02d}"
print(f"{flat_white_line:<20}{flat_white_amount:>7}")

The check compares the receipt space for space, and if a line is off it shows both versions with dots for the spaces.

receipt.py, the file you edit16 lines
# Bean There's till. Prices are in whole pennies: 320 means £3.20.
FLAT_WHITE = 320
CROISSANT = 245

# Sam's order
flat_whites = 2
croissants = 1

total = flat_whites * FLAT_WHITE + croissants * CROISSANT
print(f"Total: £{total // 100}.{total % 100:02d}")

# TODO (Step 4): replace the Total line above with three receipt lines, descriptions padded to 20
# and amounts right-aligned in 7:
#   2 x Flat white        £6.40
#   1 x Croissant         £2.45
#   Total                 £8.85

Step 5: The whole receipt

Sam tears a strip off the receipt roll to show you how a Bean There receipt starts and ends:

Bean There, receipt for Sam
2 x Flat white        £6.40
1 x Croissant         £2.45
Total                 £8.85
Thank you, see you tomorrow!

receipt.py now has a name variable next to the order. Print the first line above your three lines and the thank-you line below them. The name comes from the variable: the check prints a receipt for someone else too.

That's the receipt the Level 1 boss asks for, so keep this file in mind. In the next quest the till stops using fixed numbers and asks the customer instead.

receipt.py, the file you edit27 lines
# Bean There's till. Prices are in whole pennies: 320 means £3.20.
FLAT_WHITE = 320
CROISSANT = 245

# Sam's order
name = "Sam"
flat_whites = 2
croissants = 1

flat_white_pennies = flat_whites * FLAT_WHITE
croissant_pennies = croissants * CROISSANT
total = flat_white_pennies + croissant_pennies

flat_white_line = f"{flat_whites} x Flat white"
croissant_line = f"{croissants} x Croissant"
flat_white_amount = f"£{flat_white_pennies // 100}.{flat_white_pennies % 100:02d}"
croissant_amount = f"£{croissant_pennies // 100}.{croissant_pennies % 100:02d}"
total_amount = f"£{total // 100}.{total % 100:02d}"

print(f"{flat_white_line:<20}{flat_white_amount:>7}")
print(f"{croissant_line:<20}{croissant_amount:>7}")
print(f"{'Total':<20}{total_amount:>7}")

# TODO (Step 5): print the first line above the three lines, and the last line below them:
#   Bean There, receipt for Sam
#   ...
#   Thank you, see you tomorrow!

what you get

  • An editor and terminal in your browser
  • A check at the end of every step
  • Hints and the full solution
  • Nothing to install or configure

before you start

  • First Day at Bean There: print, variables and f-strings

Part of the Learn Python track

Lab 2 of 15. Learn Python by running a café till: receipts, orders, discounts and the Friday rush. Nothing to install.

Questions about this lab

Why does Python print 9.600000000000001?

Decimal numbers are stored in binary, so some of them come out a tiny bit off. Counting whole pennies avoids it, and this lab shows how.

Do I need to install anything?

No. Python runs right in your browser.

What you do in this lab

You keep money the way tills do, in whole pennies, then turn pennies into pounds and pence with floor division and the remainder. You meet the zero that goes missing in £3.05 and the format code that keeps it, and you line up a receipt's columns with f-string padding. Each check changes the prices and the order and runs your script again.