Write your first Elixir program: a tip calculator that handles edge cases and splits bills perfectly.

18 min read

The Magic Calculator

You know what's annoying? Splitting a shared expense among teammates.

"The total is $127.43 including tax, and we need to add 18% service fee, and there are 5 of us, but Sarah only used $15 worth of supplies..."

Your phone's calculator wasn't built for this. But Elixir was.

In this chapter, you'll build a tip calculator that handles all the weird edge cases. By the end, you'll have written actual Elixir code that solves a real problem.

Our Goal

We want a calculator that:

  • Takes a bill amount
  • Adds a tip percentage
  • Splits it evenly (or handles "Sarah only used $15 worth of supplies")
  • Shows exactly what each person pays

Creating Your First Elixir File

Elixir files end with .ex (for compiled code) or .exs (for scripts we'll run once).

Step 1: Create a new folder for your code:

  • Open your terminal/command prompt
  • Navigate to where you want your code (Desktop, Documents, wherever)
  • Create a folder:
mkdir elixir_projects
cd elixir_projects

Step 2: Create a file called tip_calculator.exs:

  • macOS/Linux: touch tip_calculator.exs
  • Windows: type nul > tip_calculator.exs

Or just use your text editor (VS Code, Sublime, Notepad, whatever) and save an empty file as tip_calculator.exs.

Step 3: Open the file in your editor.

Writing the Basic Calculator

Type this into your file:

# Tip Calculator - Your First Elixir Program

defmodule TipCalculator do
  def calculate(bill_amount, tip_percent, people_count) do
    tip_amount = bill_amount * (tip_percent / 100)
    total = bill_amount + tip_amount
    per_person = total / people_count
    
    per_person
  end
end

# Try it out
result = TipCalculator.calculate(100, 20, 4)
IO.puts("Each person pays: $#{result}")

Don't worry about what everything means yet. We'll break it down.

Running Your Program

In your terminal (in the same folder as your file):

elixir tip_calculator.exs

You should see:

Each person pays: $30.0

Congratulations! You just wrote and ran your first Elixir program.

Breaking Down the Code

Let's understand what we wrote:

defmodule TipCalculator do

A module is like a container for related code. We named ours TipCalculator because that's what it does.

Think of it like labeling a folder: "This folder contains everything about calculating tips."

def calculate(bill_amount, tip_percent, people_count) do

This defines a function called calculate. Functions are reusable pieces of code.

Our function takes three arguments (inputs):

  • bill_amount - How much the bill is
  • tip_percent - What percentage to tip
  • people_count - How many people are splitting

The Math

tip_amount = bill_amount * (tip_percent / 100)

This calculates the tip. If the bill is $100 and tip is 20%, this gives us $20.

total = bill_amount + tip_amount

Adds the tip to the bill.

per_person = total / people_count

Splits the total among everyone.

end

Every do needs an end. This closes the function and the module.

IO.puts("Each person pays: $#{result}")

This prints output to the screen. The #{result} part inserts our calculated value into the string.

Making It Better: Handling Edge Cases

Our calculator works, but it's basic. Let's handle real-world messiness.

Problem 1: Rounding to 2 decimal places (cents)

Update your function:

def calculate(bill_amount, tip_percent, people_count) do
  tip_amount = bill_amount * (tip_percent / 100)
  total = bill_amount + tip_amount
  per_person = total / people_count
  
  # Round to 2 decimal places for cents
  Float.round(per_person, 2)
end

Now try:

result = TipCalculator.calculate(127.43, 18, 5)
IO.puts("Each person pays: $#{result}")

Problem 2: What if someone pays a different amount?

Let's add a function for uneven splits:

defmodule TipCalculator do
  def calculate(bill_amount, tip_percent, people_count) do
    tip_amount = bill_amount * (tip_percent / 100)
    total = bill_amount + tip_amount
    per_person = total / people_count
    
    Float.round(per_person, 2)
  end
  
  def calculate_uneven(bill_amount, tip_percent, individual_amounts) do
    tip_amount = bill_amount * (tip_percent / 100)
    total_tip_per_dollar = tip_amount / bill_amount
    
    Enum.map(individual_amounts, fn amount ->
      their_tip = amount * total_tip_per_dollar
      their_total = amount + their_tip
      Float.round(their_total, 2)
    end)
  end
end

# Even split
result = TipCalculator.calculate(100, 20, 4)
IO.puts("Even split - Each pays: $#{result}")

# Uneven split (Sarah only spent $15 on supplies)
amounts = [35, 28, 42, 15, 30]  # What each person used
results = TipCalculator.calculate_uneven(150, 18, amounts)

IO.puts("\nUneven split:")
Enum.with_index(results, 1) |>
Enum.each(fn {amount, index} ->
  IO.puts("Person #{index} pays: $#{amount}")
end)

Run it:

elixir tip_calculator.exs

What Just Happened?

We used several new things:

Enum.map - Takes a list and transforms each item

fn amount -> ... end - An anonymous function (we'll cover this more later)

|> (the pipe operator) - Takes the result of one thing and passes it to the next

Enum.with_index - Gives us each item plus its position (starting at 1)

Enum.each - Does something for each item (in this case, printing)

Don't worry if this feels overwhelming. You're seeing the future—you'll understand all of this soon.

A Complete Example

Here's a polished version with helpful output:

defmodule TipCalculator do
  def split_bill(bill_amount, tip_percent, people) when is_integer(people) do
    tip_amount = bill_amount * (tip_percent / 100)
    total = bill_amount + tip_amount
    per_person = total / people
    
    IO.puts("Bill: $#{bill_amount}")
    IO.puts("Tip (#{tip_percent}%): $#{Float.round(tip_amount, 2)}")
    IO.puts("Total: $#{Float.round(total, 2)}")
    IO.puts("Split #{people} ways: $#{Float.round(per_person, 2)} each")
    
    Float.round(per_person, 2)
  end
  
  def split_bill(bill_amount, tip_percent, individual_orders) when is_list(individual_orders) do
    tip_amount = bill_amount * (tip_percent / 100)
    tip_ratio = tip_amount / bill_amount
    
    IO.puts("Bill: $#{bill_amount}")
    IO.puts("Tip (#{tip_percent}%): $#{Float.round(tip_amount, 2)}")
    IO.puts("Individual totals:")
    
    Enum.with_index(individual_orders, 1)
    |> Enum.each(fn {order_amount, index} ->
      their_tip = order_amount * tip_ratio
      their_total = order_amount + their_tip
      IO.puts("  Person #{index}: $#{Float.round(their_total, 2)}")
    end)
  end
end

# Example 1: Even split among friends
TipCalculator.split_bill(127.43, 18, 5)

IO.puts("\n---\n")

# Example 2: Everyone ordered different amounts
orders = [45.50, 32.00, 28.50, 21.43]
TipCalculator.split_bill(127.43, 18, orders)

What You Learned

Even though this was your first program, you already used:

  • Modules (defmodule) - containers for code
  • Functions (def) - reusable pieces of logic
  • Variables (bill_amount, tip_amount) - storing values
  • Math operators (+, -, *, /)
  • Lists ([45.50, 32.00, ...])
  • Pattern matching with guards (when is_integer, when is_list)
  • The pipe operator (|>)

Not bad for your first day!

Try It Yourself

  1. Modify the calculator to include tax calculation (add a tax_percent parameter)
  2. Make it round up to the nearest dollar for easier bill splitting
  3. Add a function that calculates just the tip amount

Remember: Breaking things is how you learn. If you get an error, read it carefully—it usually tells you exactly what went wrong.


What we just learned:

  • Elixir code goes in .exs files (for scripts) or .ex files (for compiled programs)
  • Functions live inside modules
  • Variables store values using =
  • The pipe operator |> chains operations together
  • You can have multiple functions with the same name if they do different things

Up next: Getting help when you're stuck (spoiler: the Elixir community is incredibly friendly).