{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "# Introduction to Computational Physics - Week 4 ##\n", "" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "## Table of contents week 4\n", " \n", "Introduction to Computational Physics - Week 4: [>>](#Introduction-to-Computational-Physics---Week-4) \n", "-Table of contents week 4: [>>](#Table-of-contents-week-4) \n", "-Introduction to week 4: [>>](#Introduction-to-week-4) \n", "-Python flow control: [>>](#Python-flow-control) \n", "--For loop: [>>](#For-loop) \n", "--Week 4 exercise 1: [>>](#Week-4-exercise-1) \n", "--Loops and slices: [>>](#Loops-and-slices) \n", "--Week 4 exercise 2: [>>](#Week-4-exercise-2) \n", "--Alternative forms of the for loop: [>>](#Alternative-forms-of-the-for-loop) \n", "--Week 4 exercise 3: [>>](#Week-4-exercise-3) \n", "--While statement: [>>](#While-statement) \n", "--If statement: [>>](#If-statement) \n", "--Continue and break: [>>](#Continue-and-break) \n", "--Precision of floating point numbers and flow control: [>>](#Precision-of-floating-point-numbers-and-flow-control) \n", "--Week 4 exercise 4: [>>](#Week-4-exercise-4) \n", "--Week 4 exercise 5: [>>](#Week-4-exercise-5) \n", "--Week 4 exercise 6: [>>](#Week-4-exercise-6)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "## Introduction to week 4\n", "\n", "This week we will look at how Python allows us to control the flow of programs and introduce boolean variables." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "## Python flow control\n", "\n", "We have seen how we can do calculations in Python, how we can use library functions and how we can create our own functions. Now we look at how Python allows us to decide how we would like our program to \"flow\" from one calculation or statement to the next. This allows us to deal with situations where we want to do something different depending on whether a variable is positive or negative, for example. Several ways of steering programs are provided, including the `for`, `while` and `if` statements. We look at these in the following.\n", "\n", "### For loop\n", "\n", "The `for` loop allows us to repeat sections of a program a specified number of times. The full syntax of the loop is shown below:" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Index 0\n", "Index 2\n", "Index 4\n", "Final value of index 4\n" ] } ], "source": [ "# \n", "start = 0\n", "stop = 5\n", "step = 2\n", "#\n", "for i in range(start, stop, step):\n", " print(\"Index\",i)\n", "print(\"Final value of index\",i)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "The start of the loop is indicated by the `for` statement, which is followed by the name of the index (here we use `i`) which will steer how many times the loop is executed. The values `i` should take are determined by the statement `in range(start, stop, step)` and `i`, `start`, `stop` and `step` must all be integers. The `for` line is terminated using a colon (:).\n", "\n", "When the program runs, the value of `i` is first set to `start`, then all the indented statements following the `for` statement are carried out. The value of `i` is then incremented by `step`, and if the resulting value is less than `stop`, the loop is executed again. This continues until adding `step` to `i` would give a value greater than or equal to `stop`.\n", "\n", "If `step` is one (which it often is), you can use the simpler version of the `for` loop which omits the `step` parameter:" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Index 0\n", "Index 1\n", "Index 2\n", "Final value of index 2\n" ] } ], "source": [ "# \n", "start = 0\n", "stop = 3\n", "for n in range(start, stop):\n", " print(\"Index\",n)\n", "print(\"Final value of index\",n)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "Again, the indentation indicates the body of the loop, i.e. the section of the program that is repeated. You can see that the loop doesn't run with `n = stop` and that the value of `n` on leaving the loop is the last \"allowed\" value." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "### Week 4 exercise 1\n", "\n", "Write a program using a `for` loop that produces two columns, the left column being the integers 0 to 10 and the right column the words \"zero\" to \"ten\". \n", "\n", "*Hint* Use a list containing the strings \"zero\", \"one\", \"two\" etc. and recall that you can access the elements of a list using the syntax `list[index]`!" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "### Loops and slices\n", "\n", "In weeks 2 and 3, we have looked at how \"slicing\" can be used to access array elements. One of the examples we looked at was:" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "countArr = [ 0. 1. 2. 3. 4. 5. 6. 7. 8. 9. 10.]\n", "countArr[3:6] = [3. 4. 5.]\n" ] } ], "source": [ "# \n", "import numpy as np\n", "#\n", "countArr = np.linspace(0, 10, 11)\n", "print(\"countArr =\",countArr)\n", "print(\"countArr[3:6] =\",countArr[3:6])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "This example is slightly modified below to illustrate how the parameters used in slicing are related to those in a `for` loop." ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "countArr = [0. 1. 2. 3. 4.]\n", "countArr[1:4:2] = [1. 3.]\n" ] } ], "source": [ "# \n", "countArr = np.linspace(0, 4, 5)\n", "print(\"countArr =\",countArr)\n", "print(\"countArr[1:4:2] =\",countArr[1:4:2])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "### Week 4 exercise 2\n", "\n", "Explain the role of each of the three indices between the square brackets in the statement `countArr[1:4:2])`." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "### Alternative forms of the for loop\n", "\n", "Loops can also be used to cycle through the elements in a list. An example is shown below:" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "one\n", "two\n", "three\n", "End of loop, var is three\n" ] } ], "source": [ "# \n", "loopList = [\"one\", \"two\", \"three\"]\n", "for var in loopList:\n", " print(var)\n", "print(\"End of loop, var is\",var)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "### Week 4 exercise 3\n", "\n", "Can you cycle through a tuple in the same was as through a list? Write a program similar to that for the list to test this! " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "### While statement\n", "\n", "The `while` statement offers another way of repeatedly using a section of code. An example follows:" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "test = 0.3\n", "test = 0.55\n", "test = 0.8\n", "test = 1.05\n", "Final value of test is 1.3\n" ] } ], "source": [ "# \n", "# \n", "test = 0.3\n", "limit = 1.1\n", "step = 0.25\n", "while test < limit:\n", " print(\"test =\",test)\n", " test = test + step\n", "print(\"Final value of test is\",test)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "As in the case of the for loop, the line containing `while` finishes with a colon. The body of the loop, indicated by the indentation, is executed until the condition `test < limit` is false. (It won't execute at all if the condition is false the first time it is checked.) Something must be changed in the body of the loop to ensure that at some point `test < limit` becomes false, or the loop will run for ever. In the example above, the value of `test` increases by `step` each time the while loop runs, because we set `test = test + step`.\n", "\n", "The condition that is tested has one of two values, `True` or `False`. If the statement `test < limit` is `True` execution continues, if it is `False`, it stops. As such logical conditions are used so frequently, Python has a data type, `bool` (short for _boolean_), which can take only the values `True` or `False`. We will learn more about boolean variables later." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "### If statement\n", "\n", "The `if`, `elif`, `else` statement has the syntax illlustrated below:" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "This is section B\n", "This is the end of the if statement, the value of test is 2.3\n" ] } ], "source": [ "# \n", "test = 2.3\n", "if test < 1.0:\n", " print(\"This is section A\")\n", "elif test > 2.0 and test <= 3.0:\n", " print(\"This is section B\")\n", "elif test > 3.0 and test <= 4.0:\n", " print(\"This is section C\")\n", "else:\n", " print(\"This is section D\")\n", "print(\"This is the end of the if statement, the value of test is\",test)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "Again, the lines starting with the `if`, `elif` (short for _else if_) and `else` statements must end with a colon. The code that is executed when the conditions tested in each of these lines are `True` is indented. Only the first of the sections of the `if`, `elif`, `else` block for which the condition is met is executed. _(Note, Python doesn't check the logic of your control statements, so it won't warn you if the tests in your `if` block don't make sense!)_\n", "\n", "Statements can consist of just an `if`, an `if` and an `else`, or an `if` and one or more `elif`s, or, as above, of an `if`, one or more `elif`s and an `else`.\n", "\n", "Python allows you to write the above `if`, `elif`, `else` statement in a more natural way (closer to standard mathematical notation) as follows:" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "This is section B\n", "This is the end of the if statement, the value of test is 2.3\n" ] } ], "source": [ "# \n", "test = 2.3\n", "if test < 1.0:\n", " print(\"This is section A\")\n", "elif 2.0 < test <= 3.0:\n", " print(\"This is section B\")\n", "else:\n", " print(\"This is section C\")\n", "print(\"This is the end of the if statement, the value of test is\",test)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "### Continue and break\n", "\n", "These statements allow you to modify the behaviour of a loop. In a `for` or a `while` loop, `continue` causes control to jump back to the beginning of the loop, without executing the statements after the `continue`. Two examples are shown below." ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "C\n", "n\n", "s\n", "t\n", "n\n", "t\n", "n\n", "p\n", "l\n", "Final value of letter is e\n" ] } ], "source": [ "# \n", "for letter in \"Constantinople\":\n", " if letter in \"a, e, i, o, u\":\n", " continue\n", " print(letter)\n", "print(\"Final value of letter is\",letter)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "Note that the string \"a, e, i, o u\" above could be replaced by \"a e i o u\" or \"aeiou\" and the routine would still work. It is checking whether `letter` is in the string enclosed in quotes and as `letter` is never \",\" or \" \" (there are no commas or spaces in \"Constantinople\"), their presence in the string makes no difference!\n", "\n", "Here's another example:" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "0\n", "0\n", "1\n", "10\n", "2\n", "20\n", "3\n", "4\n", "5\n", "Final value of i is 5\n" ] } ], "source": [ "# \n", "for i in range(0, 6):\n", " print(i)\n", " if i > 2:\n", " continue\n", " print(10*i)\n", "print(\"Final value of i is\",i)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "In contrast, `break` causes control to jump to the end of the loop:" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "C\n", "Final value of letter is o\n" ] } ], "source": [ "# \n", "for letter in \"Constantinople\":\n", " if letter in \"a, e, i, o, u\":\n", " break\n", " print(letter)\n", "print(\"Final value of letter is\",letter)" ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "0\n", "0\n", "1\n", "10\n", "2\n", "20\n", "3\n", "Final value of i is 3\n" ] } ], "source": [ "# \n", "for i in range(0, 6):\n", " print(i)\n", " if i > 2:\n", " break\n", " print(10*i)\n", "print(\"Final value of i is\",i)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "We see that, if the `continue` statement is used, the code in the `else` statement is executed. If the `break` condition is applied, the code in the `else` statement is not run: there is a difference between the code that is executed if a `while` loop runs completely, or if it terminates due to a `break` statement.\n", "\n", "### Precision of floating point numbers and flow control\n", "\n", "Computers use binary representations of numbers and for `floats` this results in limited precision. Similarly, addition, subtraction and other operations cause a loss of accuracy. If you want to read more, see [this article](https://docs.python.org/3/tutorial/floatingpoint.html).\n", "\n", "A consequence of this is that you should never rely on a `float` having exactly a particular value. For example, the following code is not likely to give the result you want:\n", "\n", "```Python\n", "if test == 0.1397:\n", "```\n", "\n", " Instead, you should use something like:\n", " \n", "```Python\n", "if np.abs(test - 0.1397) < 1e-10:\n", "```\n", " \n", "You can test how precise the representation of `floats` is using the following code." ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "The precision of your computer is 2.220446049250313e-16\n" ] } ], "source": [ "#\n", "#\n", "eps = 1.0\n", "while eps + 1.0 > 1.0:\n", " eps = eps/2\n", "eps = 2*eps\n", "print(\"The precision of your computer is\", eps)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "### Week 4 exercise 4\n", "\n", "Explain the functioning of the `while` loop that determines your computer's precision!" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "Python provides a function which returns the precision with which floats are represented in the `sys` (short for *system*) package:" ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Precision of float is 2.220446049250313e-16\n" ] } ], "source": [ "#\n", "import sys\n", "print(\"Precision of float is\",sys.float_info.epsilon)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "Numpy also has a function, [described here](https://docs.scipy.org/doc/numpy/reference/generated/numpy.finfo.html), which provides information on the representation of floating point numbers:" ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Precision of float is Machine parameters for float64\n", "---------------------------------------------------------------\n", "precision = 15 resolution = 1.0000000000000001e-15\n", "machep = -52 eps = 2.2204460492503131e-16\n", "negep = -53 epsneg = 1.1102230246251565e-16\n", "minexp = -1022 tiny = 2.2250738585072014e-308\n", "maxexp = 1024 max = 1.7976931348623157e+308\n", "nexp = 11 min = -max\n", "---------------------------------------------------------------\n", "\n" ] } ], "source": [ "#\n", "print(\"Precision of float is\",np.finfo(float))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "### Week 4 exercise 5\n", "\n", "Write a program using a `while` loop to calculate and print out the factorial of the first ten integers. The factorial of a number is given by $n! = n(n - 1)(n - 2)...3 \\times 2 \\times 1$, for example, $6! = 6 \\times 5 \\times 4 \\times 3 \\times 2 \\times 1 = 720$." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "### Week 4 exercise 6\n", "\n", "Write a program using a `for` loop to calculate and print out the quantity $\\sum_{n = 1}^{N} n$ with $N$ taking the values $1...15$." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.8.5" } }, "nbformat": 4, "nbformat_minor": 4 }