{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "All the IPython Notebooks in this lecture series by Dr. Milan Parmar are available @ **[GitHub](https://github.com/milaan9/02_Python_Datatypes)**\n", "" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Python Numbers, Type Conversion and Mathematics\n", "\n", "In this class, you'll learn about the different numbers used in Python, how to convert from one data type to the other, and the mathematical operations supported in Python." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Number Data Type in Python\n", "\n", "Integers, floating point numbers and complex numbers fall under Python numbers category. They are defined as **`int`**, **`float`** and **`complex`** classes in Python.\n", "\n", "Integers and floating points are separated by the presence or absence of a decimal point. For instance, 5 is an integer whereas 5.0 is a floating-point number.\n", "\n", "Complex numbers are written in the form, `x + yj`, where `x` is the real part and `y` is the imaginary part.\n", "\n", "We can use the **[type()](https://github.com/milaan9/04_Python_Functions/blob/main/002_Python_Functions_Built_in/064_Python_type%28%29.ipynb)** function to know which class a variable or a value belongs to. Similarly, the **[isinstance()](https://github.com/milaan9/04_Python_Functions/blob/main/002_Python_Functions_Built_in/034_Python_isinstance%28%29.ipynb)** function is used to check if an object belongs to a particular class.\n", "\n", "Let's look at an example:" ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "ExecuteTime": { "end_time": "2021-06-09T13:39:54.836631Z", "start_time": "2021-06-09T13:39:54.814237Z" }, "scrolled": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "\n", "(9+3j)\n", "True\n" ] } ], "source": [ "a = 6\n", "\n", "print(type(a)) # type integer\n", "\n", "print(type(5.0)) # type float\n", "\n", "c = 6 + 3j\n", "print(c + 3)\n", "\n", "print(isinstance(c, complex))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "While integers can be of any length, it is only limited by the memory available.\n", "\n", "The numbers we deal with every day are of the decimal (base 10) number system. But computer programmers (generally embedded programmers) need to work with binary (base 2), hexadecimal (base 16) and octal (base 8) number systems.\n", "\n", "In Python, we can represent these numbers by appropriately placing a prefix before that number. The following table lists these prefixes.\n", "\n", "| Number System | Prefix |\n", "|:----| :--- |\n", "| **`Binary`** | '0b' or '0B' | \n", "| **`Octal`** | '0o' or '0O' | \n", "| **`Hexadecimal`** | '0x' or '0X' | " ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "ExecuteTime": { "end_time": "2021-06-09T13:40:00.295883Z", "start_time": "2021-06-09T13:40:00.269591Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1\n", "10\n", "10\n" ] } ], "source": [ "# Example 1:\n", "\n", "# Output: 1\n", "print(0b0001) # 0001 in binary is 1 in decimal and i have use prefix '0b'\n", "\n", "# Output: 10 \n", "print(0o12) # 12 in octadecimal is 10 in decimal and i have use prefix '0o'\n", "\n", "# Output: 10\n", "print(0x000A) # 000A in hexadecimal is 10 in decimal and i have use prefix '0x'" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "ExecuteTime": { "end_time": "2021-06-09T13:40:03.236343Z", "start_time": "2021-06-09T13:40:03.229524Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "107\n", "253\n", "13\n" ] } ], "source": [ "# Example 2:\n", "\n", "# Output: 107\n", "print(0b1101011)\n", "\n", "# Output: 253 (251 + 2)\n", "print(0xFB + 0b10) # adding Hex numbers with binary numbers.\n", "\n", "# Output: 13\n", "print(0o15)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Type Conversion\n", "\n", "We can convert one type of number into another. This is also known as coercion.\n", "\n", "Operations like addition, subtraction coerce integer to float implicitly (automatically), if one of the operands is float." ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "ExecuteTime": { "end_time": "2021-06-09T13:40:07.415500Z", "start_time": "2021-06-09T13:40:07.386289Z" } }, "outputs": [ { "data": { "text/plain": [ "4.0" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "1 + 3.0 # adding integer number '1' and a float number '3.0'. The answer will be flaot number '4.0'." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can see above that 1 (integer) is coerced into 1.0 (float) for addition and the result is also a floating point number." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can also use built-in functions like **`int`**, **`float`** and **`complex`** to convert between types explicitly. These functions can even convert from **[strings](https://github.com/milaan9/02_Python_Datatypes/blob/main/002_Python_String.ipynb)**." ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "ExecuteTime": { "end_time": "2021-06-09T13:40:09.224378Z", "start_time": "2021-06-09T13:40:09.212691Z" } }, "outputs": [ { "data": { "text/plain": [ "6" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "int(6.3)" ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "ExecuteTime": { "end_time": "2021-06-09T13:40:10.144156Z", "start_time": "2021-06-09T13:40:10.126624Z" } }, "outputs": [ { "data": { "text/plain": [ "-2" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "int(-2.7)" ] }, { "cell_type": "code", "execution_count": 7, "metadata": { "ExecuteTime": { "end_time": "2021-06-09T13:40:11.438365Z", "start_time": "2021-06-09T13:40:11.430574Z" } }, "outputs": [ { "data": { "text/plain": [ "9.0" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "float(9)" ] }, { "cell_type": "code", "execution_count": 8, "metadata": { "ExecuteTime": { "end_time": "2021-06-09T13:40:14.787832Z", "start_time": "2021-06-09T13:40:14.774195Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1234567890123456789\n", "0.12345678901234568\n", "(1+2j)\n" ] } ], "source": [ "a = 1234567890123456789\n", "print (a)\n", "\n", "b = 0.1234567890123456789 # total of only 17 numbers after decimal can be printed.\n", "print (b)\n", "\n", "c = 1+2j\n", "print (c)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "When converting from float to integer, the number gets truncated (decimal parts are removed)." ] }, { "cell_type": "code", "execution_count": 9, "metadata": { "ExecuteTime": { "end_time": "2021-06-09T13:40:33.713101Z", "start_time": "2021-06-09T13:40:33.705314Z" } }, "outputs": [ { "data": { "text/plain": [ "(3+6j)" ] }, "execution_count": 9, "metadata": {}, "output_type": "execute_result" } ], "source": [ "complex('3+6j')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Python Decimal\n", "\n", "Python built-in class float performs some calculations that might amaze us. We all know that the sum of 1.1 and 2.2 is 3.3, but Python seems to disagree." ] }, { "cell_type": "code", "execution_count": 10, "metadata": { "ExecuteTime": { "end_time": "2021-06-09T13:40:37.769560Z", "start_time": "2021-06-09T13:40:37.749111Z" } }, "outputs": [ { "data": { "text/plain": [ "False" ] }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ "(1.1 + 2.2) == 3.3 # The answer should be True but..." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**What is going on?**\n", "\n", "It turns out that floating-point numbers are implemented in computer hardware as binary fractions as the computer only understands binary (0 and 1). Due to this reason, most of the decimal fractions we know, cannot be accurately stored in our computer.\n", "\n", "Let's take an example. We cannot represent the fraction 1/3 as a decimal number. This will give 0.33333333... which is infinitely long, and we can only approximate it.\n", "\n", "It turns out that the decimal fraction 0.1 will result in an infinitely long binary fraction of 0.000110011001100110011... and our computer only stores a finite number of it.\n", "\n", "This will only approximate 0.1 but never be equal. Hence, it is the limitation of our computer hardware and not an error in Python." ] }, { "cell_type": "code", "execution_count": 11, "metadata": { "ExecuteTime": { "end_time": "2021-06-09T13:40:41.836307Z", "start_time": "2021-06-09T13:40:41.826509Z" } }, "outputs": [ { "data": { "text/plain": [ "3.3000000000000003" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ "1.1 + 2.2" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "To overcome this issue, we can use the decimal module that comes with Python. While floating-point numbers have precision up to 15 decimal places, the decimal module has user-settable precision.\n", "\n", "Let's see the difference:" ] }, { "cell_type": "code", "execution_count": 12, "metadata": { "ExecuteTime": { "end_time": "2021-06-09T13:40:43.925581Z", "start_time": "2021-06-09T13:40:43.891988Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "0.1\n", "0.1000000000000000055511151231257827021181583404541015625\n" ] } ], "source": [ "import decimal\n", "\n", "print(0.1)\n", "\n", "print(decimal.Decimal(0.1))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This module is used when we want to carry out decimal calculations as we learned in school.\n", "\n", "It also preserves significance. We know 25.50 kg is more accurate than 25.5 kg as it has two significant decimal places compared to one." ] }, { "cell_type": "code", "execution_count": 13, "metadata": { "ExecuteTime": { "end_time": "2021-06-09T13:40:47.340782Z", "start_time": "2021-06-09T13:40:47.331044Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "3.3\n", "3.000\n" ] } ], "source": [ "from decimal import Decimal as D\n", "\n", "print(D('1.1') + D('2.2'))\n", "\n", "print(D('1.2') * D('2.50'))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Notice the trailing zeroes in the above example.\n", "\n", "We might ask, why not implement **`Decimal`** every time, instead of float? The main reason is efficiency. Floating point operations are carried out must faster than **`Decimal`** operations." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### When to use Decimal instead of float?\n", "\n", "We generally use Decimal in the following cases.\n", "\n", "1. When we are making financial applications that need exact decimal representation.\n", "2. When we want to control the level of precision required.\n", "3. When we want to implement the notion of significant decimal places." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Python Fractions\n", "\n", "Python provides operations involving fractional numbers through its **`fractions`** module.\n", "\n", "A fraction has a numerator and a denominator, both of which are integers. This module has support for rational number arithmetic.\n", "\n", "We can create Fraction objects in various ways. Let's have a look at them." ] }, { "cell_type": "code", "execution_count": 14, "metadata": { "ExecuteTime": { "end_time": "2021-06-09T13:40:58.266592Z", "start_time": "2021-06-09T13:40:58.204752Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "3/2\n", "9\n", "1/6\n" ] } ], "source": [ "import fractions\n", "\n", "print(fractions.Fraction(1.5))\n", "\n", "print(fractions.Fraction(9))\n", "\n", "print(fractions.Fraction(1,6))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "While creating **`Fraction`** from **`float`**, we might get some unusual results. This is due to the imperfect binary floating point number representation as discussed in the previous section.\n", "\n", "Fortunately, **`Fraction`** allows us to instantiate with string as well. This is the preferred option when using decimal numbers." ] }, { "cell_type": "code", "execution_count": 15, "metadata": { "ExecuteTime": { "end_time": "2021-06-09T13:41:01.089215Z", "start_time": "2021-06-09T13:41:01.077530Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "2476979795053773/2251799813685248\n", "11/10\n" ] } ], "source": [ "import fractions\n", "\n", "# As float\n", "# Output: 2476979795053773/2251799813685248\n", "print(fractions.Fraction(1.1)) # 1.1 is a number\n", "\n", "# As string\n", "# Output: 11/10\n", "print(fractions.Fraction('1.1')) #'1.1' is a string and not a number" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This data type supports all basic operations. Here are a few examples." ] }, { "cell_type": "code", "execution_count": 16, "metadata": { "ExecuteTime": { "end_time": "2021-06-09T13:41:04.422615Z", "start_time": "2021-06-09T13:41:04.410926Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "5854679515581645/2251799813685248\n", "2/3\n", "6/5\n", "False\n", "True\n" ] } ], "source": [ "from fractions import Fraction as F # I changed my Fraction module name to \"F\"\n", "\n", "print(F(1.3) + F(1.3))\n", "\n", "print(F(1, 3) + F(1, 3))\n", "\n", "print(1 / F(5, 6))\n", "\n", "print(F(-3, 10) > 0)\n", "\n", "print(F(-3, 10) < 0)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Python Mathematics\n", "\n", "Python offers modules like **`math`** and **`random`** to carry out different mathematics like trigonometry, logarithms, probability and statistics, etc." ] }, { "cell_type": "code", "execution_count": 17, "metadata": { "ExecuteTime": { "end_time": "2021-06-09T13:41:11.981916Z", "start_time": "2021-06-09T13:41:11.950755Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "3.141592653589793\n", "-1.0\n", "22026.465794806718\n", "3.0\n", "1.1752011936438014\n", "720\n" ] } ], "source": [ "import math\n", "\n", "print(math.pi)\n", "\n", "print(math.cos(math.pi)) # cos(pi) = -1\n", "\n", "print(math.exp(10))\n", "\n", "print(math.log10(1000)) # log10(1000) = 3\n", "\n", "print(math.sinh(1))\n", "\n", "print(math.factorial(6))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Here is the full list of functions and attributes available in the **[Python math module](https://github.com/milaan9/04_Python_Functions/blob/main/009_Python_Function_math_Module.ipynb.ipynb)**." ] }, { "cell_type": "code", "execution_count": 18, "metadata": { "ExecuteTime": { "end_time": "2021-06-09T13:41:19.484249Z", "start_time": "2021-06-09T13:41:19.465749Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "15\n", "b\n", "['d', 'c', 'e', 'a', 'b']\n", "0.8036360430009386\n" ] } ], "source": [ "import random\n", "\n", "print(random.randrange(10, 20))\n", "\n", "x = ['a', 'b', 'c', 'd', 'e'] # x is a list class of variable and it has 5 elements.\n", "\n", "# Get random choice\n", "print(random.choice(x))\n", "\n", "# Shuffle x\n", "random.shuffle(x)\n", "\n", "# Print the shuffled x\n", "print(x)\n", "\n", "# Print random element\n", "print(random.random())" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "When we run the above program we get the output as follows. (Values may be different due to the random behavior)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Here is the full list of functions and attributes available in the **[Python random module](https://github.com/milaan9/04_Python_Functions/blob/main/008_Python_Function_random_Module.ipynb)**." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "hide_input": false, "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.8" }, "toc": { "base_numbering": 1, "nav_menu": {}, "number_sections": true, "sideBar": true, "skip_h1_title": false, "title_cell": "Table of Contents", "title_sidebar": "Contents", "toc_cell": false, "toc_position": {}, "toc_section_display": true, "toc_window_display": false }, "varInspector": { "cols": { "lenName": 16, "lenType": 16, "lenVar": 40 }, "kernels_config": { "python": { "delete_cmd_postfix": "", "delete_cmd_prefix": "del ", "library": "var_list.py", "varRefreshCmd": "print(var_dic_list())" }, "r": { "delete_cmd_postfix": ") ", "delete_cmd_prefix": "rm(", "library": "var_list.r", "varRefreshCmd": "cat(var_dic_list()) " } }, "types_to_exclude": [ "module", "function", "builtin_function_or_method", "instance", "_Feature" ], "window_display": false } }, "nbformat": 4, "nbformat_minor": 2 }