Build a Friendly Bill Splitter

Build a Python bill splitter that validates input and calculates fair shares.

Introduction

30 Second Summary

Splitting a meal with friends should take seconds. One mistyped amount can turn a quick calculation into confusion or an unfair total.

In this project, you will build a friendly bill splitter with Python that recovers from common typing mistakes. It will calculate the tip, total bill, and per-person share in money format.

What You'll Build

Your finished program turns a $100 bill with a 20% tip for four people into a clear $30.00 per-person result in the terminal.

By the end of this project, you'll have:

  • An instant bill split that turns a bill amount, tip percentage, and group size into each person's share.
  • A two-decimal money summary showing the tip amount, total bill, and per-person share.
  • A friendly retry flow that catches words, negative amounts, and zero people before they break the calculation.
  • Secret Mission: Add preset tip choices plus a custom tip option.

Are there any prerequisites?

You need a Windows 10 or newer computer with internet access plus basic familiarity with opening files and folders. Step 1 sets up Python in Visual Studio Code.

Before We Start

Before the hands-on work begins, take a moment to define what your bill splitter needs to calculate. You will also consider why handling invalid input makes the program useful.

Set Up Python in Visual Studio Code

Your bill splitter needs a Python interpreter to turn its code into a running program. Visual Studio Code provides the editor around that interpreter.

The Python extension for Visual Studio Code adds Python-aware controls inside the editor. This step installs each missing piece before connecting them to one workspace.

In this step, get ready to:
  • Install the Python install manager 26.3 plus Python 3.14.8 on a supported Windows computer.
  • Install version 2026.8.0 of the Microsoft Python extension.
  • Connect the friendly-bill-splitter workspace to Python 3.14.8.
Install Python 3.14.8

Python 3.14.8 requires Windows 10 or newer. The Python install manager 26.3 manages the Python runtime on your computer.

  • Press the Windows key to open search.
  • Open your computer's system information from the search results.
  • Confirm the listed Windows release is Windows 10 or newer.

Seeing an Older Windows Version?

Python 3.14.8 supports Windows 10 or newer. An older Windows release cannot run this project version.

  • Pause this project until Windows is upgraded.

Ask for help planning the upgrade: Help me check whether my Windows computer can run Python 3.14.8.

Good. The current package installs Python install manager 26.3 on your computer.

What Did the Installer Add?

The install manager makes the py command available in Windows terminals. It can also install a requested Python runtime when that version is missing.

  • Press the Windows key to open search.
  • Type Visual Studio Code into search.
  • Press Enter to open it.
  • Click Terminal in the top menu bar.
  • Click New Terminal.

Before you run the check, do you expect this terminal to find the exact project version or a different result?

The first version check can take a minute while the manager downloads a missing Python runtime. A short pause is expected.

  • Approve the runtime installation if the manager prompts you after the check begins.
  • Check which Python 3 release is available by running this command:
py -3 --version

What Does This Command Check?

The py command asks the Windows Python manager for a Python 3 runtime. The --version option prints the runtime version without starting an interactive session.

✔️ I see Python 3.14.8

The terminal prints Python 3.14.8. Your pinned Python runtime is ready.

ⓧ I see an older version

The manager found Python 3, but the selected runtime is older than the project version. Add the exact runtime before continuing.

  • Install Python 3.14.8 with the manager by running this command:
py install 3.14.8

What Does This Command Do?

The install manager downloads the runtime tagged 3.14.8. This gives the project its required Python version.

  • Click Terminal in the VS Code menu bar.
  • Click New Terminal.
  • Check the newly installed runtime by running this command:
py -3 --version

What Does This Command Confirm?

The command asks for the available Python 3 runtime again. The fresh terminal picks up the installation you just completed.

You should now see Python 3.14.8 in the terminal.

ⓧ Command not found

Windows cannot reach the install manager yet. Reinstalling the downloaded package restores the py command.

  • Return to the Python installer you downloaded earlier.
  • Select Install.
  • Return to Visual Studio Code after the installation finishes.
  • Click Terminal in the top menu bar.
  • Click New Terminal.
  • Approve the runtime installation if the manager prompts you after the check begins.
  • Check the installation by running this command:
py -3 --version

What Does This Command Confirm?

The command confirms that the fresh terminal can reach the install manager. It also prints the Python 3 runtime version.

You should see Python 3.14.8 after the runtime installation completes.

Still Not Seeing Python 3.14.8?

A missing py command can mean the installer did not finish. An older result can mean Windows is still selecting an existing runtime.

Use the official Python Windows troubleshooting guide for installation conflicts.

Ask for help with your result: Help me fix my Python version check.

Install the Microsoft Python extension

The extension gives Visual Studio Code Python-aware editing plus run controls. It uses the interpreter you installed to run your future program.

  • Press Ctrl+Shift+X to open Extensions.
  • Search for Python.
  • Select the Python extension published by Microsoft.
  • Right-click the selected extension.
  • Choose Install Another Version.
  • Select 2026.8.0.

That's the editor side ready. The extension details now show version 2026.8.0.

Why Are Both Pieces Required?

The extension helps Visual Studio Code understand Python files. The interpreter executes the instructions inside those files.

🙋‍♀️ Can't Find the Pinned Extension Version?

Confirm that the extension is published by Microsoft. Open Install Another Version from that extension's menu.

Ask for help finding the release: Help me install the pinned Python extension.

Create and connect the project workspace

A workspace keeps the bill splitter files under one named folder. Selecting an interpreter tells Visual Studio Code which Python runtime belongs to that workspace.

  • Click File in the Visual Studio Code menu bar.
  • Click Open Folder.
  • Select your Desktop in the folder picker.
  • Create a folder named friendly-bill-splitter with the folder picker's creation control.
  • Select the new friendly-bill-splitter folder.
  • Click Select Folder.
  • Approve the folder trust prompt if Visual Studio Code displays one.

You should see friendly-bill-splitter at the top of the Explorer sidebar. This confirms the empty project workspace is open.

  • Press Ctrl+Shift+P to open the command palette.
  • Enter Python: Select Interpreter.
  • Select Python: Select Interpreter from the results.
  • Choose Python 3.14.8 from the interpreter list.

Visual Studio Code now shows Python 3.14.8 as the selected interpreter for this workspace.

Before you run the final check, what exact version do you expect the fresh workspace terminal to report?

  • Click Terminal in the top menu bar.
  • Click New Terminal.
  • Verify the selected Python installation by running this command:
py -3 --version

What Does the Final Check Prove?

The fresh terminal confirms that the workspace can reach Python 3. It prints the runtime version that your project is ready to use.

You should see Python 3.14.8 in the terminal. Your editor now has the exact interpreter required for the bill splitter.

Does the Terminal Show a Different Version?

Confirm that Python 3.14.8 remains selected for the friendly-bill-splitter workspace. Create another fresh terminal after changing the interpreter.

Ask for help comparing the terminal with the selected interpreter: Help me fix the Python version in my VS Code workspace.

Your Python workspace is ready. Next, you'll build the first working version of your bill splitter.

Build the First Bill Splitter

Python 3.14.8 now runs inside your Visual Studio Code workspace.

A small working version gives you an immediate result before you add safety checks. You will collect three values from the terminal before calculating each person's share.

In this step, get ready to:
  • Create a Python file that collects the bill details.
  • Calculate the tip plus each person's share.
  • Display the result with f-strings plus two decimal places.
Collect the bill details

Variables give each piece of user input a name that later calculations can use.

  • Select the New File button in the VS Code Explorer sidebar for the friendly-bill-splitter folder.
  • Enter bill_splitter.py as the file name.

You'll see an empty bill_splitter.py file in the editor plus the Explorer sidebar.

  • Add the program title plus its three input variables by copying this code into bill_splitter.py:
print("Friendly Bill Splitter")

bill = float(input("Bill amount: $"))
tip_percent = float(input("Tip percentage: "))
people = int(input("How many people are splitting the bill? "))

What Does This Code Do?

  • The first print() call gives the program a visible title.
  • Each input() call pauses the program until you enter an answer.
  • The float() calls convert the bill plus tip percentage into decimal numbers.
  • The int() call converts the number of people into a whole number.
  • Save bill_splitter.py.

Before you run the file, which three questions do you expect the terminal to ask?

  • Run the active file from the VS Code Command Palette by selecting Python: Run Python File in Terminal.
  • Enter 100 when the program asks for the bill amount.
  • Enter 20 when the program asks for the tip percentage.
  • Enter 4 when the program asks how many people are splitting the bill.

The terminal shows Friendly Bill Splitter before asking the three questions in order.

After your third answer, control returns to the terminal. Good, your program can now collect every value needed for the split.

Don't See the Three Prompts?

Confirm that bill_splitter.py is the active editor file. Check that each opening parenthesis plus quotation mark has a matching closing character.

Run the file again after saving your corrections.

Help me fix the input section of my bill splitter.

Calculate the split

The tip is a percentage of the original bill. The final share divides the bill plus tip across the number of people.

  • Switch back to bill_splitter.py in the VS Code editor.
  • Place your cursor below people = int(input("How many people are splitting the bill? ")).
  • Add the three calculations by copying this code:
tip_amount = bill * tip_percent / 100
total = bill + tip_amount
per_person = total / people

How Does the Calculation Work?

  • The tip_amount calculation applies the selected percentage to bill.
  • The total calculation adds the tip to the original bill.
  • The per_person calculation divides the total by people.
  • Save bill_splitter.py.

Before you rerun the file, do you expect these valid values to complete every calculation?

  • Run the active file from the VS Code Command Palette by selecting Python: Run Python File in Terminal.
  • Enter 100 for the bill amount.
  • Enter 20 for the tip percentage.
  • Enter 4 for the number of people.

The terminal accepts all three values before returning control to you. This clean run proves that the arithmetic completes with those inputs.

Does the Calculation Stop?

Compare the calculation lines with the code above. Check the spelling of tip_percent plus tip_amount.

Use a value of 4 for people during this test.

Help me fix the calculations in my bill splitter.

Display and verify the result

An f-string places a variable's value inside output text. The .2f format specifier displays a decimal value with two digits after the decimal point.

  • Place your cursor below per_person = total / people in bill_splitter.py.
  • Add the formatted summary by copying this code:
print("\nYour split")
print(f"Tip amount: ${tip_amount:.2f}")
print(f"Total bill: ${total:.2f}")
print(f"Each person pays: ${per_person:.2f}")

How Is the Result Formatted?

  • The \n character starts the summary on a new line.
  • Each f-string inserts one calculated value into its label.
  • Each .2f format specifier keeps the money display at two decimal places.
  • Save bill_splitter.py.

Before you run the completed program, what share do you predict for a bill of 100 with a 20 percent tip split between 4 people?

  • Run the active file from the VS Code Command Palette by selecting Python: Run Python File in Terminal.
  • Enter 100 for the bill amount.
  • Enter 20 for the tip percentage.
  • Enter 4 for the number of people.

The terminal shows Tip amount: $20.00 plus Total bill: $120.00.

The final line reads Each person pays: $30.00.

That's your first working bill splitter: valid inputs now produce a complete currency summary.

Does Your Result Look Different?

Confirm that the tip calculation divides by 100. Check that each output variable ends with the .2f format specifier.

Compare your three test inputs with 100, 20, plus 4.

Help me compare my bill splitter result with the expected output.

✔️ Awesome, I've got everything!

Great. Save bill_splitter.py once more so your working version is ready for the next test.

ⓧ I'd like to double check the full code

Compare your saved bill_splitter.py with this complete version.

print("Friendly Bill Splitter")

bill = float(input("Bill amount: $"))
tip_percent = float(input("Tip percentage: "))
people = int(input("How many people are splitting the bill? "))

tip_amount = bill * tip_percent / 100
total = bill + tip_amount
per_person = total / people

print("\nYour split")
print(f"Tip amount: ${tip_amount:.2f}")
print(f"Total bill: ${total:.2f}")
print(f"Each person pays: ${per_person:.2f}")

Your splitter handles valid numbers plus displays the result clearly. Next, you will test a typing mistake that this first version cannot recover from.

Expose the Input Failure

Your first Python bill splitter already turns clean numeric answers into a formatted result.

The current conversion path trusts every answer. A deliberate word exposes that assumption before you add any protection.

In this step, get ready to:
  • Run the current calculator with one deliberately mismatched answer.
  • Read the traceback from the bottom upward.
  • Identify the numeric conversion that stops the program.
Trigger the invalid input

Your earlier test used answers that matched all three numeric conversions. This test keeps the first two answers valid while the final answer probes the unprotected input path.

Before you run the file, do you expect it to reach the bill summary after two is entered?

  • Return to bill_splitter.py in Visual Studio Code.
  • Run the active file with Python: Run Python File in Terminal.
  • Enter 100 when the program asks for the bill amount.
  • Enter 20 when the program asks for the tip percentage.
  • Enter two when the program asks how many people are splitting the bill.

The program stops before Your split. The traceback ends with ValueError.

Why Did the Program Stop?

The input() call returns two as a string. The int() call cannot construct an integer from that text.

Python raises ValueError. The calculation cannot continue without a value for people.

🙋‍♀️ Did the Program Reach the Summary?

  • Run the file again if you entered 2 instead of two.
  • Enter 100 at the bill prompt.
  • Enter 20 at the tip prompt.

Help me reproduce the planned input failure.

Trace the failing conversion

A traceback records where the program was running when an exception occurred. Its bottom line names the exception.

The statement above that final line points to the expression Python could not complete.

  • Read the final line of the traceback to identify ValueError.
  • Move one line upward to find this exact statement:
people = int(input("How many people are splitting the bill? "))

What Does This Line Reveal?

  • The input() call supplies the text typed in the terminal.
  • The int() call attempts the whole-number conversion before assigning a value to people.
  • The failed conversion prevents people from receiving a value during this run.
  • Match the traceback statement to the same statement in bill_splitter.py.
  • Identify the integer conversion around the final answer as the operation that stopped the program.

The terminal connects ValueError to the exact people assignment. Your source file remains unchanged after this test.

Use these tabs to confirm that the experiment changed only what you know about the program.

✔️ Awesome, I've got everything!

Your traceback identifies the failing conversion. Your existing bill_splitter.py file is still unchanged.

ⓧ I'd like to double check the full code

Compare bill_splitter.py with this unchanged reference file.

print("Friendly Bill Splitter")

bill = float(input("Bill amount: $"))
tip_percent = float(input("Tip percentage: "))
people = int(input("How many people are splitting the bill? "))

tip_amount = bill * tip_percent / 100
total = bill + tip_amount
per_person = total / people

print("\nYour split")
print(f"Tip amount: ${tip_amount:.2f}")
print(f"Total bill: ${total:.2f}")
print(f"Each person pays: ${per_person:.2f}")

You found the exact point where untrusted text breaks the calculation. Next, you'll make that input path recover from mistakes before the arithmetic begins.

Add Friendly Input Validation

Your earlier test exposed the fragile spot in your Python bill splitter. One unexpected word stops the calculation before anyone sees their share.

Friendly input validation gives the user another chance after a mistake. Two reusable functions also keep impossible values away from the calculation.

In this step, get ready to:
  • Retry nonnumeric bill or tip entries.
  • Reject bill or tip values below zero.
  • Require at least one person before calculating.
Validate bill and tip amounts

Bill amounts can contain decimal places. The same rule applies to tip percentages. get_non_negative_number() converts each answer to a number. It keeps asking until the answer is numeric and at least zero.

  • Select bill_splitter.py in the Explorer sidebar of Visual Studio Code.
  • Place your cursor above print("Friendly Bill Splitter").
  • Add the bill and tip validation function with this code:
def get_non_negative_number(prompt):
    while True:
        try:
            value = float(input(prompt))
            if value < 0:
                print("Please enter 0 or more.")
            else:
                return value
        except ValueError:
            print("Please enter a number, such as 42.50.")

What Does This Function Do?

  • The prompt parameter lets the same function display different questions.
  • The while True loop repeats until the function reaches return value.
  • The try block attempts to convert the user's answer with float().
  • The except ValueError block catches an invalid numeric conversion. The program prints a retry message instead of stopping.
  • The range check rejects values below zero. A valid value leaves the function through return.
  • Save bill_splitter.py.
  • Use Python: Run Python File in Terminal to check the new function for syntax errors.
  • Enter 100 for the bill amount.
  • Enter 20 for the tip percentage.
  • Enter 4 for the number of people.

You'll see the same $20.00 tip plus $30.00 per-person result. This confirms that the new function has valid syntax.

Seeing a Syntax Error?

Confirm that the function appears above print("Friendly Bill Splitter"). Each line inside the function must stay indented as shown.

Check that except ValueError: lines up with try:.

Help me fix the syntax in my validation function.

  • Find bill = float(input("Bill amount: $")) below the program title.
  • Find tip_percent = float(input("Tip percentage: ")) directly below it.
  • Replace those direct conversions with these function calls:
bill = get_non_negative_number("Bill amount: $")
tip_percent = get_non_negative_number("Tip percentage: ")

Why Use the Function Twice?

Both lines use the same validation rules. Each call supplies its own prompt before returning a usable number.

The returned values still go into bill and tip_percent. The calculation below them can continue unchanged.

  • Save bill_splitter.py.

Before you run the file, predict whether typing ten will stop the program or trigger another bill prompt.

  • Use Python: Run Python File in Terminal to start the updated program.
  • Enter ten for the bill amount.

You'll see Please enter a number, such as 42.50. The bill prompt appears again without a traceback.

  • Enter 100 at the repeated bill prompt.
  • Enter -5 for the tip percentage.

You'll see Please enter 0 or more. The tip prompt appears again because a negative percentage cannot continue.

  • Enter 20 at the repeated tip prompt.
  • Enter 4 for the number of people.

You'll see Each person pays: $30.00 after both corrected values reach the calculation.

Still Crashing on Bill or Tip Input?

Confirm that both input lines call get_non_negative_number(). A remaining direct float(input(...)) conversion can still raise an uncaught error.

Check that except ValueError: remains inside the function's loop.

Help me trace why my bill or tip validation still crashes.

Validate the number of people

A group size needs a whole number. It must also contain at least one person so the program never divides by zero.

The second function combines integer conversion with that minimum. Its retry loop returns only a safe value for people.

  • Place your cursor below the closing line of get_non_negative_number().
  • Add the people validation function with this code:
def get_number_of_people():
    while True:
        try:
            people = int(input("How many people are splitting the bill? "))
            if people < 1:
                print("Please enter at least 1 person.")
            else:
                return people
        except ValueError:
            print("Please enter a whole number, such as 2.")

How Does People Validation Differ?

  • The int() conversion accepts a whole-number answer for the group size.
  • The people < 1 check rejects zero plus negative group sizes.
  • The except ValueError block catches words plus decimal answers that cannot become an integer.
  • A valid group size reaches return people. That value makes division safe.
  • Save bill_splitter.py.
  • Use Python: Run Python File in Terminal to check the second function for syntax errors.
  • Enter 100 for the bill amount.
  • Enter 20 for the tip percentage.
  • Enter 4 for the number of people.

You'll see Each person pays: $30.00 again. The second function is defined without breaking the working calculation.

Does the New Function Cause an Error?

Confirm that def get_number_of_people(): starts at the far left. Keep its loop plus error handling indented beneath it.

Leave a blank line between the two function definitions. This makes their boundaries easier to compare.

Help me fix my people validation function.

  • Find people = int(input("How many people are splitting the bill? ")) below the tip input line.
  • Replace the direct conversion with this function call:
people = get_number_of_people()

What Changes in the Main Program?

The main program now receives people from get_number_of_people(). The function handles every retry before the calculation begins.

  • Save bill_splitter.py.

✔️ Awesome, I've got everything!

Your two validation functions are in place. All three inputs now call them.

ⓧ I'd like to double check the full code

  • Compare your saved bill_splitter.py with this complete reference:
def get_non_negative_number(prompt):
    while True:
        try:
            value = float(input(prompt))
            if value < 0:
                print("Please enter 0 or more.")
            else:
                return value
        except ValueError:
            print("Please enter a number, such as 42.50.")


def get_number_of_people():
    while True:
        try:
            people = int(input("How many people are splitting the bill? "))
            if people < 1:
                print("Please enter at least 1 person.")
            else:
                return people
        except ValueError:
            print("Please enter a whole number, such as 2.")


print("Friendly Bill Splitter")

bill = get_non_negative_number("Bill amount: $")
tip_percent = get_non_negative_number("Tip percentage: ")
people = get_number_of_people()

tip_amount = bill * tip_percent / 100
total = bill + tip_amount
per_person = total / people

print("\nYour split")
print(f"Tip amount: ${tip_amount:.2f}")
print(f"Total bill: ${total:.2f}")
print(f"Each person pays: ${per_person:.2f}")

How Is the File Organized?

The two validation functions appear before the program title. This makes both functions available when the three input lines call them.

The calculation plus formatted summary remain below the validated inputs. Only safe values can reach that section.

Test every retry path

Before you run the completed file, predict how many retry messages you will see after entering one word plus two impossible values.

  • Use Python: Run Python File in Terminal to start the final validation test.
  • Enter ten for the bill amount.

You'll see Please enter a number, such as 42.50. The program asks for the bill amount again.

  • Enter 100 at the repeated bill prompt.
  • Enter -5 for the tip percentage.

You'll see Please enter 0 or more. The program asks for the tip percentage again.

  • Enter 20 at the repeated tip prompt.
  • Enter 0 for the number of people.

You'll see Please enter at least 1 person. The program asks for the group size again.

  • Enter 4 at the repeated people prompt.

You'll see Tip amount: $20.00. You'll also see Total bill: $120.00.

You'll see Each person pays: $30.00 at the end. Every invalid answer has been corrected without a crash.

Does a Retry Path Behave Differently?

Confirm that bill plus tip_percent call get_non_negative_number(). Confirm that people calls get_number_of_people().

Check each comparison carefully. Amounts use value < 0. The group size uses people < 1.

Help me diagnose a failed retry path.

You did it. Your bill splitter now turns common typing mistakes into another chance to answer.

Secret mission

Add a Tip Menu

Give your bill splitter preset choices for 10%, 15%, and 20%. Keep a custom option for any other percentage. Then prove that both paths preserve the program's friendly validation.

Clean Up Your Resources

Clean Up Your Resources

Choose whether to keep your project ready, pause your work for later, or delete the project entirely. Everything runs locally, so there are no ongoing costs.

Resources you used:

  • The friendly-bill-splitter folder containing your Python program in bill_splitter.py.

Keep everything running

No action is needed. This option keeps your bill splitter ready for more testing or future improvements.

  • Keep the friendly-bill-splitter folder on your computer.
  • Leave bill_splitter.py unchanged so you can run the finished calculator again.

Pause - I'll come back to this later

The bill splitter stops after each completed run. Pausing only requires closing your editor while keeping the project files.

  • Close Visual Studio Code after the program finishes.
  • Keep the friendly-bill-splitter folder so you can continue later.

Your project remains stored locally without using memory or creating costs.

Delete - I don't want to use this again

Deleting this folder permanently removes only the bill splitter project. Python 3.14.8 and Visual Studio Code stay installed for future projects.

  • Close Visual Studio Code.
  • Press the Windows key to open search.
  • Type File Explorer into search.
  • Press Enter to open File Explorer.
  • Return to the location where you created the friendly-bill-splitter folder.
  • Delete the friendly-bill-splitter folder.

Confirm that the folder no longer appears in File Explorer. This verifies that bill_splitter.py and the rest of the local project were removed.

Nice Work!

Nice Work!

You did it! You built a Friendly Bill Splitter in Python that calculates each share from terminal input.

You've learned how to:

  • Calculate the tip amount. Find the total bill. Divide that total into a per-person share.
  • Convert terminal input with float() plus int(). Format every money value to two decimal places with f-strings.
  • Replace a crashing ValueError with input validation that retries typing mistakes. Reject negative amounts plus zero people before calculation.
  • Secret Mission: Add a tip menu with preset percentages. Keep a custom tip option for any other value.

Ready to quiz yourself?