{ "cells": [ { "cell_type": "raw", "metadata": {}, "source": [ "---\n", "execute:\n", " freeze: auto\n", " cache: true\n", "---" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Boolean Variables and Conditional Execution\n", "\n", "\n", "[Jupyter Notebook](https://lancejnelson.github.io/PH135/jupyter/booleans.ipynb)\n", "\n", "## Boolean Variables\n", "\n", "We have learned about three types of variables in Python: ints, floats, and strings. Another variable type is a boolean, which can be one of two values: `True` or `False`. You can assign a boolean variable in the same way that you assign numbers or string, using `=`" ] }, { "cell_type": "code", "metadata": {}, "source": [ "myBool = True" ], "execution_count": null, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`True` *must be* capitalized so don't try `true` or it won't be a boolean" ] }, { "cell_type": "code", "metadata": {}, "source": [ "#| echo: true\n", "#| eval: false\n", "\n", "myBool = true" ], "execution_count": null, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Boolean Logic\n", "\n", "Often you will want to check to see if some condition is true. For example, maybe you want to know if the radius of a certain satellite's orbit is bigger or smaller than Mercury's orbit. To perform this check, there are several boolean operators that will return `True` or `False`. Take note of the boolean operators shown in the cell below along with the comments added to explain what they do." ] }, { "cell_type": "code", "metadata": {}, "source": [ "r1 = 3.5e8\n", "r2 = 2.7e6\n", "\n", "r1 > r2 # Is r1 greater than r2\n", "r1 < r2 # Is r1 less than r2\n", "r1 >= r2 # Is r1 greater than or equal to r2\n", "r1 <= r2 # Is r1 less than or equal to r2\n", "r1 != r2 # Is r1 not equal to r2\n", "r1 == r2 # Is r1 equal to r2" ], "execution_count": null, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "A word of caution about comparing Python floats using `==` is in order here.\n", "Python floats are stored as a 53-digit, base-2 binary number(that's a\n", "mouthful). If you're interested in what that means, we can talk more.\n", "If you're not that interested, just know that when you define a float\n", "in Python, the number that is stored in the computer is not\n", "*exactly* the number that you think it is. This can cause\n", "problems when you are comparing two numbers that you think should be\n", "equal but actually aren't equal in the computer.[^decimal] The code below illustrates this problem.\n", "\n", "\n", "[^decimal]:There is a\n", " library called `Decimal` that will fix a lot of these\n", " problems. " ] }, { "cell_type": "code", "metadata": {}, "source": [ "a = 0.1\n", "b = 3 * a\n", "c = 0.3\n", "print(b==c) # Are they the same number? You would think they would\n", " # be right?\n", "print(\" {:.5f} \".format(b)) # They sure look the same.\n", "print(\" {:.5f} \".format(c)) # They sure look the same.\n", "print(\" {:.45f} \".format(b)) #b--- out to 45 decimal places\n", "print(\" {:.45f} \".format(c)) #c--- out to 45 decimal places" ], "execution_count": null, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The first two print statements display the value of `b` and `c` to five\n", "decimal places. The second two print statements force Python\n", "to display the value of `b` and `c` out to 45 decimal\n", "places. Notice that the true value of `b` is not _exactly_\n", "equal to 0.3. This is why the statement `print(b==c)` returns\n", "`False`. The take home message here is that comparing two floats\n", "to see if they are equal **is always a bad idea.** A better way to\n", "check to see if two floats are equal (or close enough that we can say\n", "they are equal) is to check if the absolute value of their difference\n", "is very small, like this:" ] }, { "cell_type": "code", "metadata": {}, "source": [ "a = 0.1\n", "b = 3 * a\n", "c = 0.3\n", "print(abs(b - c) < 1e-10)" ], "execution_count": null, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Compound Comparisons (Logical Operators)\n", "\n", "Comparisons like those shown above can be chained together to make compound comparisons using the `and`, `or`, and `not` operators. \n", "\n", "\n", "| Operator | Description |\n", "| -------- | ----------- |\n", "| and | Tests for both being `True`|\n", "| or | Tests for either being `True`|\n", "| not | Tests for `False`|\n", "\n", "\n", "The `and` operator requires both inputs to be `True` in order to return `True` while the `or` operator requires only one input to be `True` in order to evaluate at `True`. The `not` operator is different in that it only takes a single input value and returns `True` if and only if the input is `False`. It is a test for `False`. \n", "\n", "\n", "Truth tables are a good way to visualize the output from compound comparisons.\n", "\n", "| p | q| p and q| p or q|\n", "| -------- | --- | --- | ----------- |\n", "| `True`| `True`| `True`| `True` |\n", "| `True`| `False`| `False`| `True` |\n", "| `False`| `True`| `False`| `True` |\n", "| `False`| `False`| `False`| `False` |\n", "\n", "\n", "\n", "\n", "As a simple example, suppose you know the density ($\\rho$) and speed of light (c) for two materials and you'd like to know if both values are bigger for material 1 or material 2.\n", "\n", "\n", "\n", ">**_To Do:_**\n", ">\n", ">1. Predict the output for each compound comparison given below. Add your guess as a comment.\n", ">2. Now add appropriately-placed print statements to check your guesses.\n", ">3. Modify your guess as needed and discuss any questions with a neighbor.\n" ] }, { "cell_type": "code", "metadata": {}, "source": [ "c1 = 2.5e8\n", "c2 = 2.48e8\n", "ρ1 = 450\n", "ρ2 = 580\n", "\n", "c1 > c2 and ρ1 > ρ2\n", "c1 < c2 and ρ1 < ρ2\n", "c1 > c2 and ρ1 < ρ2\n", "c1 < c2 and ρ1 > ρ2\n", "\n", "c1 > c2 and not ρ1 > ρ2\n", "c1 < c2 and not ρ1 < ρ2\n", "\n", "c1 > c2 or ρ1 > ρ2\n", "c1 < c2 or ρ1 < ρ2" ], "execution_count": null, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Tests for Inclusion \n", " \n", " You can check for inclusion using the Python `in` operator. This provides an easy way to see if a character (or word) is present in a long string. Let's say you have a long string that contains the names of Jupyter's moons (there are 79 of them!!) and you want to see if a certain moon is included in the list. The `in` statement let's us quickly test to see if it is in the list. (see example below) " ] }, { "cell_type": "code", "metadata": {}, "source": [ "jupytermoons = \"Metis,Adrastea,Amalthea,Thebe,Io,Europa,Ganymede,Callisto,Themisto,Leda,Himalia,Lysithea,Elara,Dia,Carpo,Euporie,Thelxinoe,Euanthe,Helike,Orthosie,Iocaste,Praxidike,Harpalyke,Mneme,Hermippe,Thyone,Ananke,Herse,Aitne,Kale,Taygete,Chaldene,Erinome,Aoede,Kallichore,Kalyke,Carme,Callirrhoe,Eurydome,Pasithee,Kore,Cyllene,Eukelade,Pasiphae,Hegemone,Arche,Isonoe,Sinope,Sponde,Autonoe,Megaclite\"\n", "\n", "\"Cyllene\" in jupytermoons" ], "execution_count": null, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Conditions\n", "\n", "\n", "*Conditions* allow the user to specify if and when certain lines or blocks of code are executed. Specifically, when a condition is true, the block of *indented* code directly below it will run.\n", "\n", "\n", "### `if` statement\n", "\n", "The `if` statement is used to control when a block of code runs. Its usage is shown below ending in a colon and the block of code below indented with *four spaces*. Using the **Tab** key will also produce four spaces." ] }, { "cell_type": "code", "metadata": {}, "source": [ "jupytermoons = \"Metis,Adrastea,Amalthea,Thebe,Io,Europa,Ganymede,Callisto,Themisto,Leda,Himalia,Lysithea,Elara,Dia,Carpo,Euporie,Thelxinoe,Euanthe,Helike,Orthosie,Iocaste,Praxidike,Harpalyke,Mneme,Hermippe,Thyone,Ananke,Herse,Aitne,Kale,Taygete,Chaldene,Erinome,Aoede,Kallichore,Kalyke,Carme,Callirrhoe,Eurydome,Pasithee,Kore,Cyllene,Eukelade,Pasiphae,Hegemone,Arche,Isonoe,Sinope,Sponde,Autonoe,Megaclite\"\n", "\n", "if \"Cyllene\" in jupytermoons:\n", " found = True\n", " print(\"Found Cyllene in the list\")\n", " \n", "if \"Matis\" in jupytermoons:\n", " found = True\n", " print(\"Found Matis in the list\")" ], "execution_count": null, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "If the boolean statement after `if` is true, the indented code below it will run. If the statement is false, Python just skips the indented lines below. The end of an `if` code block is determined by the indentation; to signal the end of the block, simply step back the indentation. \n", "\n", "### `else` Statement\n", "\n", "Sometimes there will be an alternate block of code that you want to run if the `if` statement evaluates to `False`. The `else` statement is used to specify this block of code, as shown below." ] }, { "cell_type": "code", "metadata": {}, "source": [ "jupytermoons = \"Metis,Adrastea,Amalthea,Thebe,Io,Europa,Ganymede,Callisto,Themisto,Leda,Himalia,Lysithea,Elara,Dia,Carpo,Euporie,Thelxinoe,Euanthe,Helike,Orthosie,Iocaste,Praxidike,Harpalyke,Mneme,Hermippe,Thyone,Ananke,Herse,Aitne,Kale,Taygete,Chaldene,Erinome,Aoede,Kallichore,Kalyke,Carme,Callirrhoe,Eurydome,Pasithee,Kore,Cyllene,Eukelade,Pasiphae,Hegemone,Arche,Isonoe,Sinope,Sponde,Autonoe,Megaclite\"\n", "\n", "if \"Cyllene\" in jupytermoons:\n", " found = True\n", " print(\"Found Cyllene in the string\")\n", "else:\n", " found = False\n", " print(\"Did not find Cyllene in the string\")\n", "\n", " \n", "if \"Matis\" in jupytermoons:\n", " found = True\n", " print(\"Found Matis in the string\")\n", "else:\n", " found = False\n", " print(\"Did not find Matis in the string\")" ], "execution_count": null, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Notice that the `else` statement must be followed by a colon and the block of code to be executed is indented, just as in the `if` block. \n", "\n", "\n", "There is an additional statement called the `elif` statement, short for \"else if\", which is used to add extra conditions below the initial `if` statement. The block of code below the `elif` statement only runs if the `if` statement is false and the `elif` statement is true. An example is given below.\n" ] }, { "cell_type": "code", "metadata": {}, "source": [ "jupytermoons = \"Metis,Adrastea,Amalthea,Thebe,Io,Europa,Ganymede,Callisto,Themisto,Leda,Himalia,Lysithea,Elara,Dia,Carpo,Euporie,Thelxinoe,Euanthe,Helike,Orthosie,Iocaste,Praxidike,Harpalyke,Mneme,Hermippe,Thyone,Ananke,Herse,Aitne,Kale,Taygete,Chaldene,Erinome,Aoede,Kallichore,Kalyke,Carme,Callirrhoe,Eurydome,Pasithee,Kore,Cyllene,Eukelade,Pasiphae,Hegemone,Arche,Isonoe,Sinope,Sponde,Autonoe,Megaclite\"\n", "\n", "if \"Matis\" in jupytermoons:\n", " foundMatis = True\n", " print(\"Found Matis in the string\")\n", "elif \"Cyllene\" in jupytermoons:\n", " foundCyllene = True\n", " print(\"Found Cyllene in the string.\")\n", "else:\n", " foundCyl = False\n", " foundMatis = False\n", " print(\"Did not find Cyllene or Matis in the string\")" ], "execution_count": null, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "It is worth noting that `else` statements are not required. If you leave the `else` statement off and the `if` statement is false, no code block will execute.\n", "\n", "\n", "## Flash Cards\n", "\n", "1. How do you check to see if one value is **greater than or equal to** another one?\n", "2. Which boolean operators should **never** be used to compare floats?\n", "3. What is the correct way to determine if two floats are equal to each other (or very close)?\n", "4. When will the statement `p and q` evaluate to `True`?\n", "5. When will the statement `p or q` evaluate to `True`?\n", "6. How do you check to see if a certain sequence of characters is present in a string?\n", "7. When constructing an `if` block how does Python know what code to execute if the condition is `True`?\n", "8. Recite Helaman 5:12.\n", "\n", "## Exercises\n", "1. A transcendental equation is one that cannot be solved using paper and pencil techniques (All the stuff you learned in algebra class). The following equation is an example of a transcendental equation: ${\\sin(x)\\over x} = 0.3$\n", "\n", " 1. Write an `if`-`else` code block that checks to see if a guessed `x` value is a solution to this equation. Do not use the `==` operator but rather check to see if the absolute value of the difference is less than $1 \\times 10^-4$. Each block of the `if`-`else` should print an appropriate sentence indicating whether the guessed value is a solution or not. The `else` block should also print off the absolute value of the difference so you know how far off your guess was.\n", " 2. Now use guess and check to find a value for `x` that is a solution to this equation.\n" ] }, { "cell_type": "code", "metadata": {}, "source": [ "#| eval: true\n" ], "execution_count": null, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "2. (Thermoelectrics) A thermoelectric is a material that converts thermal energy into electrical energy. and much research is devoted to finding new materials that exhibit this behavior. Good thermoelectrics tend to be materials with high electrical conducitivity ($\\sigma > 7 \\times 10^5~\\Omega^{-1} \\text{m}^{-1}$ ) **and** low thermal conductivity ($\\kappa< 2.0$ W/ m K ). Write an `if`-`else` code block that checks to see if a material's electrical conductivity is above the threshold **and** its thermal conductivity is below the threshold. Then choose some values for the conductivities and test your `if`-`else` block.\n" ] }, { "cell_type": "code", "metadata": {}, "source": [ "sigma = 0 # Electrical Conductivity\n", "kappa = 0 # Thermal Conductivity" ], "execution_count": null, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "3. Alloys are often represented by a string containing the elements in the alloy and the relative number of atoms for each element. For example, \"Cu2Au\" (Copper-2-Gold) means that the alloy is made of copper and gold and there are two copper atoms for every gold atom. Write some python code that calculates the total number of atoms in an alloy. The code should include a print statement to display the result. Then check your code on the alloys in the table below. You can assume that all elements have two-character symbols even though that isn't true; we won't consider any one-character symbols in this problem.\n", "\n", "Hints: \n", "\n", "1. The possible lengths for the strings are 4 (one atom per element), 5 (one atom for one element and more for the other), or 6 (more than one atom for both elements).\n", "2. My code for this problem was about 15 lines long and it required a nested `if`-`else` block (an `if`-`else` inside of an `if` block). \n", "3. You may find the `isdigit()` function to be helpful. Do you remember how to use it and what it does?\n", "\n", "| | |Alloy | | |\n", "|--------|--------|--------|--------|--------|\n", "| \"Cr3Si\"| \"Al2Cu\"| \"NbPd3\"| \"CaIn2\"| \"Al3Zr4\"|" ] }, { "cell_type": "code", "metadata": {}, "source": [ "alloy = \"CaIn2\" \n" ], "execution_count": null, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "4. The quadratic equation has two solutions and they can be positive, negative, or complex. Often the complex and/or negative solutions are not relavant/meaningful. Write an `if/elif/else` block of code that checks what type of solutions will result and only displays the real, positive solution(s) if they exist. If there is no positive solution, the code should display a message indicating such. Then check your code with the values given below. As a reminder, here is the quadratic equation: $$ x = {- b \\pm \\sqrt{b^2 - 4 a c} \\over 2a} $$\n", "\n", "\n", "`a = 2, b = 3, c = 8` (no real solutions)\n", "\n", "`a = 1, b = -3, c = 2` (two positive solutions)\n", "\n", "`a = 1, b = -3, c = -2` (one positive solution and one negative solution)" ] }, { "cell_type": "code", "metadata": {}, "source": [ "# Python code here." ], "execution_count": null, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "5. (Triangle Classification) There is a simple criteria to determine whether a triangle can be formed from a set of specified side lengths. The criteria states that the sum of any two sides must be larger than the third side. This criteria must be satisified for all possible combinations of two sides if the triangle is to be valid. If the triangle is valid, the angles can be found by first using the law of cosines to find the first two angles $$c^2 = a^2 + b^2 - 2 a b \\cos(C)$$ and then choosing the third angle so that the sum of the three angles add up to $180^\\circ$.\n", "\n", " 1. Write some code that checks to see if a valid triangle can be formed from the given side lengths. \n", " 2. If a triangle can be formed, use the law of cosines to calculate the triangle's angles. Print the angles in degrees. Check your code for several choices of side lengths to verify that it is working.\n", " 3. All valid triangles are classified according to the largest angle present (acute, obtuse, and right) and also according to their side lengths (scalene - no sides equal, isoscelese - two sides equal and equilateral - all sides equal). Modify your code to determine the classification of a triangle (i.e. obtuse scalene) and print that classification to screen.\n" ] }, { "cell_type": "code", "metadata": {}, "source": [ "from numpy import arccos,pi\n", "\n", "#a = # Side length 1\n", "#b = # Side length 1\n", "#c = # Side length 1" ], "execution_count": null, "outputs": [] } ], "metadata": { "kernelspec": { "name": "python3", "language": "python", "display_name": "Python 3 (ipykernel)" } }, "nbformat": 4, "nbformat_minor": 4 }