Mix.install([
{:jason, "~> 1.4"},
{:kino, "~> 0.9", override: true},
{:youtube, github: "brooklinjazz/youtube"},
{:hidden_cell, github: "brooklinjazz/hidden_cell"},
{:visual, github: "brooklinjazz/visual"},
{:smart_animation, github: "brooklinjazz/smart_animation"}
])
Upon completing this lesson, a student should be able to answer the following questions.
- What are integers and floats?
- What are arithmetic operators?
- What is the order of operations, and how can you alter it using round brackets
()
?
Arithmetic is a branch of mathematics that involves the manipulation of numbers. Often functional programming languages like Elixir get a reputation for requiring advanced math skills. The same goes for programming in general, but especially functional programming.
Let's dispel that myth. While some programming fields require advanced math skills, many do not. Generally, web development only requires simple arithmetic (adding, subtracting, dividing, multiplying, etc), and even then, we let the computers do most of the heavy lifting!
Rest assured, this will not be a math course, nor will most real-world applications demand advanced math knowledge.
Computers were originally built to perform computations that humans could not perform easily or at all. So out of the box, we can perform mathematical calculations.
Humans have been building mathematical machines for ages and the computers that run our programs are by far the most powerful!
Integers are whole numbers, including negative numbers.
flowchart LR
... --> -5 --> -4 --> -3 --> -2 --> -1 --> 0 --> 1 --> 2 --> 3 --> 4 --> 5 --> 6[...]
You can use integers directly in your programs.
1
1023
1235460
-1
-100
-123512
Often you'll use integers for representing ages, days, years, cash values, and more.
In the Elixir cell below, replace 1
the biggest integer you can think of (until you get bored).
We'll show you how many digits the number has when you re-evaluate the Elixir cell.
If you've used any other programming language, you might be surprised! Integers in Elixir are unbounded, meaning they have no maximum size.
Contrast that with a language like JavaScript which has a maximum safe integer size of 9007199254740991
.
Elixir makes that look tiny!
biggest_integer = 1
Kino.Markdown.new(~s(
integer: #{biggest_integer}\n
digits: #{biggest_integer |> Integer.digits() |> Enum.count()}
))
You can see unbounded integers in action in the following animation. Watch how the number of digits constantly grows! Move on to the next section when you're satisfied that integers are truly unbounded.
To avoid distorting your screen we use mathematical notation
SmartAnimation.new(1..100_000_000, fn i ->
max = 10 ** 80
integer_display = (10 ** i < max && 10 ** i) || "$10^{#{i}}$"
Kino.Markdown.new("""
integer: #{integer_display}\n
digits: #{Integer.digits(10 ** i) |> Enum.count()}
""")
end)
Floats refer to floating-point numbers.
Floats are used to represent decimal numbers in your program like 1.22
, 2.3
, 1.0
, and even 0.0
.
flowchart LR
... --> -0.0001 --> -0.001 --> -0.01 --> -0.1 --> 0.0 --> 0.1 --> 0.01 --> 0.001 --> 0.0001 --> a[...]
You can use floats directly in your program just like with integers.
0.0
3.5
12123.123123123
Floats can have varying precision. The precision of a float is the number of digits after the decimal point.
For example, the precision of the float 1.2
is one. the precision of the float 1.22
is two.
You'll often use floats for representing percentages. For example, you might want to represent a progress bar as a percentage.
In the Elixir cell below, try changing the float percentage
to any float between 0.0
and 100.0
and see how the loading bar changes! Replace 50.0
with your answer and reevaluate the cell.
percentage = 50.0
Kino.Markdown.new(~s(
<div style=\"height: 20px; width: 100%; background-color: grey\">
<div style=\"height: 20px; width: #{percentage}%; background-color: green; color: white;\">#{percentage}%</div>
</div>
))
Take great care when performing calculations with floats.
Computers are limited to how precise they can be when representing floating-point numbers. Therefore, it's possible to have unexpected results!
For example, what do you think 1.2 + 1.4
returns? Probably 2.6
right? Nope!
You'll see the actual answer is 2.5999999999999996
in the Elixir cell below.
1.2 + 1.4
Why do computers have these errors? Well that requires a fairly in-depth understanding of how the computer hardware works under the hood. For our purposes it's enough to be aware that it happens.
If you are curious, Computerphile has an excellent video on why
YouTube.new("https://www.youtube.com/watch?v=PZRI1IfStY0")
Due to these errors, do not use floats to represent money even though it might seem
intuitive to translate $1.29
into 1.29
.
Instead, you'll often use integers to represent pennies so $1.29
becomes 129
.
Alternatively, the Money library provide utilities for working with money.
In the Elixir cell below, enter some floating-point addition that returns an unexpected result.
Using arithmetic operators, we can add +
, subtract -
, multiply *
and divide /
.
We also have two special arithmetic operators, div/2
for integer division and rem/2
for
remainder.
Arithmetic operators manipulate both positive and negative integers and floats.
As previously mentioned in the lesson on floats, arithmetic operations on floats may result in floating-point errors.
7 + 5
You can create entire equations by writing operators one after the other. So long as there is a valid number (integer or float) on the operator's left and right hand side.
4 + 3 + 2 + 1
The following code will crash because there is a dangling +
operator. The error says TokenMissingError and expression is incomplete
because we did not complete the mathematical expression. Whenever our code crashes,
Elixir lets you know why with an error message.
2 +
As mentioned, adding floats together may result in floating point errors, so only use them when a small amount of innaccuracy isn't an issue.
1.2 + 1.4
You can use floats and integers together in arithmetic expressions.
1.2 + 4
1.5 + 3.5 + 3 + 4.1 + 9
You can also add negative and positive numbers together. Adding a negative number is the same as subtracting a positive number.
8 + -9
Adding negative numbers might feel unintuitive, so it's rare to write code like this, but it's useful to know you can.
In the Elixir cell below, add two massive numbers together that you couldn't do in your head.
We can subtract numbers with the minus -
operator.
20 - 12
Like with addition, we can subtract floats and integers in any combination.
2.5 - 10
10 - 2.5 - 2.1
Floating-point errors can still occur.
1.3 - 1.2
Subtracting a negative is the same as adding a positive.
10 - -1
In the Elixir cell below, subtract two massive numbers together.
Computers can efficiently multiply numbers. Under the hood, multiplication is just
repeated addition. For example, 5 * 5
is 5 + 5 + 5 + 5 + 5
.
10 * 10
Multiplication can still result in floating-point errors.
2.2 * 2.1
You can multiply integers and floats both positive and negative in combination, like with addition and subtraction.
2 * 30 * -2 * 1.4
In the Elixir cell below, multiply two massive numbers together.
We can also divide numbers. However, in Elixir there are two operators for division.
There is the /
operator, which will always return a float
, and the div
operator,
which will always return an integer
(rounded down).
10 / 5
div
is a function. You will learn more about functions in the future.
For now, it's enough to know that div
allows you to take two numbers and divide them.
div(10, 5)
Remember that div
always rounds values down, so 1.5
becomes 1
.
div(3, 2)
There's a limit to how precise numbers can be in any computer program, so you should always take care when using fractions that don't divide evenly. You can also run into the same floating-point calculation issues discussed in the floats lesson.
For example, notice that 10 / 3
is 3.3333333333333335
.
10 / 3
In the Elixir cell below, divide 223
by 71
using /
to get a nice slice of pi. Your answer
should be close to 3.14
.
Divide 100
by 3
using div
. Your answer should be 33
.
The exponent operator in Elixir is **
.
That means that 10 ** 2
is 10 to the power of 2. Mathematically that's the same as 10 * 10
.
10 ** 3
means 10 * 10 * 10
. If you would like a more in-depth explanation of exponents, there's
a video by Khan Academy.
YouTube.new("https://www.youtube.com/watch?v=XZRQhkii0h0")
10 ** 2
In the Elixir cell below, Use the **
operator to determine 10
to the power of 214
.
Example solution
10 ** 214
Calculations in Elixir follow the BEDMAS order of operations. BEDMAS stands for brackets, exponents, division, multiplication, addition, and subtraction.
That means that the following will evaluate 5 * 2 before 5 + 5.
5 + 5 * 2
So it first evaluates into.
5 + 10
To get the result of 15.
15
Here's the same statement in an Elixir cell so that you can confirm the result is 15.
5 + 5 * 2
Had it been evaluated from left to right, the result would have been 20.
5 + 5 * 2
10 * 2
20
You might notice the B in BEDMAS stands for brackets. You can use brackets in your program override the order of operations.
(5 + 5) * 2
(10) * 2
20
Here's the same statement in an Elixir cell for you to confirm its result is 20.
(5 + 5) * 2
In the Elixir cell below,
Use brackets ()
to alter the return value of the expression below to be 200
instead of 110
.
Example solution
(10 + 10) * 10
10 + 10 * 10
A remainder is the amount left when you divide one number by the other.
For example, if you divide 5
by 2
, the remainder is 1
.
That's because 2
goes into 5
twice and leaves a remainder of 1
.
If you're not familiar with remainders, here's a video by Khan Academy.
YouTube.new("https://www.youtube.com/watch?v=P1qyjdh_sIw")
rem(5, 2)
In programming, we can use remainders to check if a number is evenly divisible by a number.
For example, a number is even if rem(number, 2)
equals 0
.
rem(6, 2)
Where as an odd number will have a remainder of 1
.
rem(5, 2)
You'll also use remainders to cycle through numbers but then reset back to 0 when you hit a limit. You don't need to know how to do this yet, but it will be helpful in future lessons.
Here we have an animation to show the remainder of a growing number divided by 10 to help you visualize this effect.
SmartAnimation.new(1..100_000_000, fn i ->
Kino.Markdown.new("""
```elixir
rem(#{i}, 10) = #{rem(i, 10)}
```
""")
end)
Find the remainder of 10
divided by 3
using rem/2
.
flowchart
1
2
3
4
5
6
7
8
9
10
style 1 fill:lightgreen
style 2 fill:lightgreen
style 3 fill:lightgreen
style 4 fill:lightyellow
style 5 fill:lightyellow
style 6 fill:lightyellow
style 7 fill:lightcoral
style 8 fill:lightcoral
style 9 fill:lightcoral
Example solution
rem(10, 3)
Enter your solution below.
Consider the following resource(s) to deepen your understanding of the topic.
DockYard Academy now recommends you use the latest Release rather than forking or cloning our repository.
Run git status
to ensure there are no undesirable changes.
Then run the following in your command line from the curriculum
folder to commit your progress.
$ git add .
$ git commit -m "finish Arithmetic reading"
$ git push
We're proud to offer our open-source curriculum free of charge for anyone to learn from at their own pace.
We also offer a paid course where you can learn from an instructor alongside a cohort of your peers. We will accept applications for the June-August 2023 cohort soon.