1.5. Conditionals#
A conditional statement allows a block of code to be executed only when a given logical condition is satisfied. Before introducing the so-called if
statement, we need to learn how to express these conditions.
1.5.1. Boolean expressions#
A boolean expression is an expression that is either true or false. For example, the operator ==
compares two operands and returns true
if they are equal and false
otherwise:
123 == 123
true
123 == 100 + 23
true
123 == -123
false
true
and false
are special values that belong to the type
Bool:
typeof(true)
Bool
typeof(false)
Bool
typeof(45 == 45)
Bool
Other comparison or relational operators are listed below
Operator |
Name |
---|---|
|
equality |
|
inequality (type \ne + TAB) |
|
less than |
|
less than or equal to (type \le + TAB) |
|
greater than |
|
greater than or equal to (type \ge + TAB) |
and here are some more simple examples:
23 ≤ -5
false
4 ≠ 44
true
Note that comparison between floating point numbers and integers work as you would expect:
1.0 == 1
true
1.000000000001 == 1
false
Finally a warning about notation: A common mistake is to use single =
for comparison (since it mimics the mathematical notation), but this is incorrect. Single =
is an assignment operator, double ==
is a comparison operator.
1.5.2. Logical operators#
More complex boolean expressions can be formulated using the following logical operators:
&& (and), || (or), and ! (not).
Note that &&
has higher precedence than ||
does.
Examples:
3 < 4 && -15 > -10
false
3 < 4 || -15 > -10
true
!(-4 ≥ 4) && (1 > 2 || 1 < 2)
true
1.5.2.1. Chained comparisons#
In Julia, comparisons can be arbitrarily chained:
1 < 2 <= 2 < 3 == 3 > 2 >= 1 == 1 < 3 != 5
true
This syntax is convenient to, for example, determine if a variable is in a given range:
x = -2.3
-3 ≤ x ≤ 4
true
1.5.2.2. The if-statement#
We are now ready to define the if
statement for conditional execusion. It has the following syntax:
if x < y
println("x is less than y")
elseif x > y
println("x is greater than y")
else
println("x is equal to y")
end
First
x < y
is evaluated, iftrue
then the corresponding block is evaluatedOtherwise,
x > y
is evaluated, iftrue
then the corresponding block is evaluatedIf neither expression is
true
, the else block is evaluatedThe
elseif
andelse
blocks are optional, andelseif
can be repeated
# Examples of if-else statements
function check_x(x)
if 0 ≤ x ≤ 10
println("x is between 0 and 10")
elseif !(x < 0)
println("x is not between 0 and 10, and x is not negative (meaning x > 10)")
else
println("x is not between 0 and 10, and x is not not negative (meaning x is negative)")
end
end
check_x (generic function with 1 method)
check_x(π)
x is between 0 and 10
check_x(10.000001)
x is not between 0 and 10, and x is not negative (meaning x > 10)
check_x(2^63) # trick question - causes Int64 overflow
x is not between 0 and 10, and x is not not negative (meaning x is negative)
1.5.2.3. Short-circuit evaluation#
In a series of boolean expressions connected by these operators, only the minimum number of expressions are evaluated as are necessary to determine the final boolean value of the entire chain. For example:
In the expression
a && b
, the subexpressionb
is only evaluated ifa
evaluates totrue
In the expression
a || b
, the subexpressionb
is only evaluated ifa
evaluates tofalse
This allows for convenient error handling, for example the following code will never take the square root of a negative number (which would cause an error):
x = -3
if x ≥ 0 && sqrt(x) < 10
# do something
else
println("Sorry, need a non-negative number with square root strictly less than 10")
end
Sorry, need a non-negative number with square root strictly less than 10
1.5.3. Example: Fibonacci, handling special cases#
One common use for if-statements is the handling of special cases. For example, the Fibonacci sequence is defined by \(F_0 = 0\), \(F_1 = 1\), and the recurrence relation
In the implementation below, the special cases \(F_0\) and \(F_1\) are handled separately, and for all other numbers the recurrence relation is used.
function fibonacci(n)
# First special cases
if n == 0
return 0
elseif n == 1
return 1
else
# General case n ≥ 2 - initialize and iterate
Fkold = 0
Fk = 1
for k = 2:n
Fknew = Fk + Fkold
# Swap previous values
Fkold = Fk
Fk = Fknew
end
return Fk
end
end
fibonacci (generic function with 1 method)
fibonacci(10)
55
fibonacci(1000) # Again be careful with overflow of Int64, but this one is OK
817770325994397771
1.5.4. Example: Multiples of 3 and 5#
Project Euler, Problem 1:
If we list all the natural numbers below 10 that are multiples of 3 or 5, we get 3, 5, 6 and 9. The sum of these multiples is 23.
Find the sum of all the multiples of 3 or 5 below 1000.
Let us create a general function that solves the problem for numbers below a given value n
. Note that we can use the remainder operator %
to check if a number is a multiple of another number.
function PE1(n)
s = 0
for i = 1:n-1
if i % 3 == 0 || i % 5 == 0
s += i
end
end
s
end
PE1 (generic function with 1 method)
We can now confirm that our function gives the right answer for the example provided:
PE1(10)
23
and we can answer the main question:
PE1(1000)
233168