{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Iteration "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Iteration is key to many scientific computing tasks; Julia has `for` and `while` loops.\n",
"\n",
"A block of code (e.g. the body of a `for` loop or of a function) must end with the keyword `end`.\n",
"It is usually written with 4 spaces of indentation (although this is not actually necessary; indentation is not significant in Julia). "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Ranges "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"A common style of `for` loop runs over a *range* of numbers. Julia has a special syntax and types to represent ranges:"
]
},
{
"cell_type": "code",
"execution_count": 18,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"1\n",
"2\n",
"3\n",
"4\n",
"5\n"
]
}
],
"source": [
"R = 1:5\n",
"for i in R\n",
" println(i)\n",
"end"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"R = 1:5"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"[1] What is the value of the expression that assigns the range to the variable? What type is the resulting variable? What about if we put floating-point numbers in a range? Guess the syntax to include a different step size."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"These types do not store the numbers that they contain, i.e. they are memory-efficient. In general, Julia tries to be as efficient as possible in this way. They are *iterable*, which means that an [iteration protocol]() is defined for ranges; this is what allows the `for` to work."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Vectors "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"If we do in fact require the list of numbers in a range, we can obtain it via"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"v = collect(1:5)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"[1] The resulting object is a vector. What is its exact type? An alternative way of writing this is `Vector{Int64}`."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Vectors may be created using square brackets, `[` and `]`:\n",
"\n",
" v = [3, 4, 7]. \n",
" \n",
"They may be iterated over with a `for`; elements are also extracted and set using square brackets:\n",
"\n",
" v[3] = 10"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"[2] Make a function `my_mean` that takes a vector and calculates its mean. [To do this, guess the name of the function that finds the number of elements in a vector and use tab completion to check your guess]. Test it with different inputs. What type does it return? What about for inputs that are complex numbers? Does the function also work for ranges?"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Exercise: Babylonian algorithm "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The Babylonian algorithm is an efficient way to calculate the square root $\\sqrt{y}$ of a number $y$, given by\n",
"\n",
"$$x_{n+1} := \\textstyle \\frac{1}{2} (x_n + \\textstyle \\frac{y}{x_n}).$$\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"[1] Implement this in a function that accepts an argument `y`. We can specify that `y` must be real by annotating the argument as\n",
"\n",
" y :: Real\n",
"\n",
"[2] What happens if we call the function with an argument that is not real?"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Storing results by growing vectors "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Suppose we now wish to store a list of the values $(x_n)$ generated during the algorithm. For this, we use the *same* vector type. Entries can be added to a one-dimensional vector using the functions `push!` and `append!`."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"[3] Make a vector and work out how `push!` and `append!` work, and how they differ. [You can also use e.g. `?push!` to get the available help/documentation on a given command.]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"[4] Return the list of intermediate results from the Babylonian algorithm, in addition to the final answer. [Julia allows us to return several values from a function, and assign them one by one:\n",
"\n",
" function f(x)\n",
" x, x^2 # return the pair x, x^2\n",
" end\n",
" \n",
" y, z = f(3)\n",
"]\n",
"\n",
"[5] What is the type of `f(3)`? [NB: this has changed in v0.4.]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"You may worry that growing vectors dynamically using `push!` is expensive. \n",
"A size for the vector can be suggested using `sizehint`; an alternative is to create a vector of the correct size using `zeros` and fill it using element access. However, `push!` is usually sufficient. \n",
"\n",
"[Remember that any concerns about efficiency should be *checked by profiling* rather than guessing: it is often difficult to predict the behaviour of modern compilers and processors.]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Conditionals "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Conditionals are written using standard C-type boolean operators: `<`, `>`, `<=`, `>=`, `==` (equality), `!=` (not equal).\n",
"\n",
"[1] Define a variable `x` to be `3`. What are the value and type of the boolean expressions `x < 3` and `x <= 3`?\n",
"\n",
"They are joined by boolean operators `&&` (and) and `||` (or).\n",
"\n",
"The structure of a conditional is\n",
"\n",
" if \n",
" \n",
" \n",
" \n",
" elseif \n",
" \n",
" \n",
" elseif \n",
" \n",
" \n",
" else\n",
" \n",
" \n",
" end\n",
" \n",
"Both the `elseif` and `else` are optional, but don't forget the final `end`!"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"[2] Define a function to sample a random number from the discrete distribution taking values $1$, $2$, $3$ and $4$ with probabilities $0.1$, $0.2$, $0.3$ and $0.4$, respectively.\n",
"\n",
"Take a large number of samples and make a histogram (bar chart) to check that the probabilities are sampled correctly.\n",
"\n",
"[Note that arbitrary discrete distributions can be sampled efficiently using the `Categorical` type in the `Distributions`package.]"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Julia 0.3.8-pre",
"language": "julia",
"name": "julia 0.3"
},
"language_info": {
"name": "julia",
"version": "0.3.10"
}
},
"nbformat": 4,
"nbformat_minor": 0
}