diff --git a/05_numbers.ipynb b/05_numbers.ipynb index df7598c..d6409ba 100644 --- a/05_numbers.ipynb +++ b/05_numbers.ipynb @@ -92,7 +92,7 @@ { "data": { "text/plain": [ - "140218620396752" + "139928698315984" ] }, "execution_count": 2, @@ -2115,7 +2115,7 @@ { "data": { "text/plain": [ - "140218620574432" + "139928698489496" ] }, "execution_count": 63, @@ -4070,7 +4070,7 @@ } }, "source": [ - "[getcontext()](https://docs.python.org/3/library/decimal.html#decimal.getcontext) shows us how the [decimal](https://docs.python.org/3/library/decimal.html) module is set up. By default, the precision is set to $28$ significant digits, which is roughly twice as many as with `float` objects." + "[getcontext()](https://docs.python.org/3/library/decimal.html#decimal.getcontext) shows us how the [decimal](https://docs.python.org/3/library/decimal.html) module is set up. By default, the precision is set to `28` significant digits, which is roughly twice as many as with `float` objects." ] }, { @@ -4282,7 +4282,7 @@ } }, "source": [ - "Arithmetic operations between `Decimal` and `int` objects work as the latter are inherently precise: The results are *new* `Decimal` objects." + "`Decimal` numbers *preserve* the **significant digits**, even in cases where this is not needed." ] }, { @@ -4290,14 +4290,14 @@ "execution_count": 137, "metadata": { "slideshow": { - "slide_type": "slide" + "slide_type": "fragment" } }, "outputs": [ { "data": { "text/plain": [ - "Decimal('42')" + "Decimal('0.30000')" ] }, "execution_count": 137, @@ -4306,7 +4306,7 @@ } ], "source": [ - "42 + Decimal(42) - 42" + "Decimal(\"0.10000\") + Decimal(\"0.20000\")" ] }, { @@ -4321,7 +4321,7 @@ { "data": { "text/plain": [ - "Decimal('42')" + "True" ] }, "execution_count": 138, @@ -4330,7 +4330,18 @@ } ], "source": [ - "10 * Decimal(42) / 10" + "Decimal(\"0.10000\") + Decimal(\"0.20000\") == Decimal(\"0.3\")" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "source": [ + "Arithmetic operations between `Decimal` and `int` objects work as the latter are inherently precise: The results are *new* `Decimal` objects." ] }, { @@ -4345,7 +4356,7 @@ { "data": { "text/plain": [ - "Decimal('0.1')" + "Decimal('42')" ] }, "execution_count": 139, @@ -4353,6 +4364,54 @@ "output_type": "execute_result" } ], + "source": [ + "42 + Decimal(42) - 42" + ] + }, + { + "cell_type": "code", + "execution_count": 140, + "metadata": { + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "Decimal('42')" + ] + }, + "execution_count": 140, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "10 * Decimal(42) / 10" + ] + }, + { + "cell_type": "code", + "execution_count": 141, + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "Decimal('0.1')" + ] + }, + "execution_count": 141, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "Decimal(1) / 10" ] @@ -4370,7 +4429,7 @@ }, { "cell_type": "code", - "execution_count": 140, + "execution_count": 142, "metadata": { "slideshow": { "slide_type": "fragment" @@ -4383,7 +4442,7 @@ "'0.10000000000000000000000000000000000000000000000000'" ] }, - "execution_count": 140, + "execution_count": 142, "metadata": {}, "output_type": "execute_result" } @@ -4394,7 +4453,7 @@ }, { "cell_type": "code", - "execution_count": 141, + "execution_count": 143, "metadata": { "slideshow": { "slide_type": "-" @@ -4407,7 +4466,7 @@ "'0.10000000000000000555111512312578270211815834045410'" ] }, - "execution_count": 141, + "execution_count": 143, "metadata": {}, "output_type": "execute_result" } @@ -4429,7 +4488,7 @@ }, { "cell_type": "code", - "execution_count": 142, + "execution_count": 144, "metadata": { "slideshow": { "slide_type": "slide" @@ -4443,7 +4502,7 @@ "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mTypeError\u001b[0m Traceback (most recent call last)", - "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0;36m1.0\u001b[0m \u001b[0;34m*\u001b[0m \u001b[0mDecimal\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m42\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", + "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0;36m1.0\u001b[0m \u001b[0;34m*\u001b[0m \u001b[0mDecimal\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m42\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", "\u001b[0;31mTypeError\u001b[0m: unsupported operand type(s) for *: 'float' and 'decimal.Decimal'" ] } @@ -4465,7 +4524,7 @@ }, { "cell_type": "code", - "execution_count": 143, + "execution_count": 145, "metadata": { "slideshow": { "slide_type": "slide" @@ -4478,7 +4537,7 @@ "Decimal('2')" ] }, - "execution_count": 143, + "execution_count": 145, "metadata": {}, "output_type": "execute_result" } @@ -4489,7 +4548,7 @@ }, { "cell_type": "code", - "execution_count": 144, + "execution_count": 146, "metadata": { "slideshow": { "slide_type": "-" @@ -4502,7 +4561,7 @@ "Decimal('1.414213562373095048801688724')" ] }, - "execution_count": 144, + "execution_count": 146, "metadata": {}, "output_type": "execute_result" } @@ -4526,7 +4585,7 @@ }, { "cell_type": "code", - "execution_count": 145, + "execution_count": 147, "metadata": { "slideshow": { "slide_type": "fragment" @@ -4539,7 +4598,7 @@ "Decimal('1.999999999999999999999999999')" ] }, - "execution_count": 145, + "execution_count": 147, "metadata": {}, "output_type": "execute_result" } @@ -4558,14 +4617,14 @@ } }, "source": [ - "The [quantize()](https://docs.python.org/3/library/decimal.html#decimal.Decimal.quantize) method allows us to cut off a `Decimal` number at any digit that is smaller than the set precision while adhering to the rounding rules from math.\n", + "The [quantize()](https://docs.python.org/3/library/decimal.html#decimal.Decimal.quantize) method allows us to [quantize](https://www.dictionary.com/browse/quantize) (i.e., \"round\") a `Decimal` number at any precision that is *smaller* than the set precision. It looks at the number of decimals (i.e., to the right of the period) of the numeric argument we pass in.\n", "\n", - "For example, as the overall imprecise value of `two` still has a precision of $28$ digits, we can correctly round it to the first $20$ digits." + "For example, as the overall imprecise value of `two` still has an internal precision of `28` digits, we can correctly round it to *four* decimals (i.e., `Decimal(\"0.0001\")` has four decimals)." ] }, { "cell_type": "code", - "execution_count": 146, + "execution_count": 148, "metadata": { "slideshow": { "slide_type": "fragment" @@ -4575,16 +4634,44 @@ { "data": { "text/plain": [ - "Decimal('2')" + "Decimal('2.0000')" ] }, - "execution_count": 146, + "execution_count": 148, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "two.quantize(20)" + "two.quantize(Decimal(\"0.0001\"))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We can never round a `Decimal` number and obtain a greater precision than before: The `InvalidOperation` exception tells us that *loudly*." + ] + }, + { + "cell_type": "code", + "execution_count": 149, + "metadata": {}, + "outputs": [ + { + "ename": "InvalidOperation", + "evalue": "[]", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mInvalidOperation\u001b[0m Traceback (most recent call last)", + "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mtwo\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mquantize\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mDecimal\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"0.1\"\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;34m**\u001b[0m \u001b[0;36m28\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", + "\u001b[0;31mInvalidOperation\u001b[0m: []" + ] + } + ], + "source": [ + "two.quantize(Decimal(\"0.1\") ** 28)" ] }, { @@ -4595,12 +4682,12 @@ } }, "source": [ - "Consequently, with this little workaround $\\sqrt{2}^2 = 2$ works even in Python." + "Consequently, with this little workaround $\\sqrt{2}^2 = 2$ works, even in Python." ] }, { "cell_type": "code", - "execution_count": 147, + "execution_count": 150, "metadata": { "slideshow": { "slide_type": "skip" @@ -4613,13 +4700,13 @@ "True" ] }, - "execution_count": 147, + "execution_count": 150, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "two.quantize(20) == 2" + "two.quantize(Decimal(\"0.0001\")) == 2" ] }, { @@ -4635,7 +4722,7 @@ }, { "cell_type": "code", - "execution_count": 148, + "execution_count": 151, "metadata": { "slideshow": { "slide_type": "fragment" @@ -4648,13 +4735,13 @@ "True" ] }, - "execution_count": 148, + "execution_count": 151, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "(Decimal(2).sqrt() ** 2).quantize(20) == 2" + "(Decimal(2).sqrt() ** 2).quantize(Decimal(\"0.0001\")) == 2" ] }, { @@ -4670,7 +4757,7 @@ }, { "cell_type": "code", - "execution_count": 149, + "execution_count": 152, "metadata": { "slideshow": { "slide_type": "skip" @@ -4683,85 +4770,13 @@ "Decimal('NaN')" ] }, - "execution_count": 149, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "Decimal(\"nan\")" - ] - }, - { - "cell_type": "code", - "execution_count": 150, - "metadata": { - "slideshow": { - "slide_type": "skip" - } - }, - "outputs": [ - { - "data": { - "text/plain": [ - "False" - ] - }, - "execution_count": 150, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "Decimal(\"nan\") == Decimal(\"nan\") # nan's never compare equal to anything, not even to themselves" - ] - }, - { - "cell_type": "code", - "execution_count": 151, - "metadata": { - "slideshow": { - "slide_type": "skip" - } - }, - "outputs": [ - { - "data": { - "text/plain": [ - "Decimal('Infinity')" - ] - }, - "execution_count": 151, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "Decimal(\"inf\")" - ] - }, - { - "cell_type": "code", - "execution_count": 152, - "metadata": { - "slideshow": { - "slide_type": "skip" - } - }, - "outputs": [ - { - "data": { - "text/plain": [ - "Decimal('-Infinity')" - ] - }, "execution_count": 152, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "Decimal(\"-inf\")" + "Decimal(\"nan\")" ] }, { @@ -4776,7 +4791,7 @@ { "data": { "text/plain": [ - "Decimal('Infinity')" + "False" ] }, "execution_count": 153, @@ -4785,7 +4800,7 @@ } ], "source": [ - "Decimal(\"inf\") + 42 # Infinity is infinity, concrete numbers loose its meaning" + "Decimal(\"nan\") == Decimal(\"nan\") # nan's never compare equal to anything, not even to themselves" ] }, { @@ -4800,7 +4815,7 @@ { "data": { "text/plain": [ - "True" + "Decimal('Infinity')" ] }, "execution_count": 154, @@ -4808,6 +4823,78 @@ "output_type": "execute_result" } ], + "source": [ + "Decimal(\"inf\")" + ] + }, + { + "cell_type": "code", + "execution_count": 155, + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "Decimal('-Infinity')" + ] + }, + "execution_count": 155, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "Decimal(\"-inf\")" + ] + }, + { + "cell_type": "code", + "execution_count": 156, + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "Decimal('Infinity')" + ] + }, + "execution_count": 156, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "Decimal(\"inf\") + 42 # Infinity is infinity, concrete numbers loose its meaning" + ] + }, + { + "cell_type": "code", + "execution_count": 157, + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "True" + ] + }, + "execution_count": 157, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "Decimal(\"inf\") + 42 == Decimal(\"inf\")" ] @@ -4825,7 +4912,7 @@ }, { "cell_type": "code", - "execution_count": 155, + "execution_count": 158, "metadata": { "slideshow": { "slide_type": "skip" @@ -4839,7 +4926,7 @@ "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mInvalidOperation\u001b[0m Traceback (most recent call last)", - "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mDecimal\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"inf\"\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;34m+\u001b[0m \u001b[0mDecimal\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"-inf\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", + "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mDecimal\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"inf\"\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;34m+\u001b[0m \u001b[0mDecimal\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"-inf\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", "\u001b[0;31mInvalidOperation\u001b[0m: []" ] } @@ -4850,7 +4937,7 @@ }, { "cell_type": "code", - "execution_count": 156, + "execution_count": 159, "metadata": { "slideshow": { "slide_type": "skip" @@ -4864,7 +4951,7 @@ "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mInvalidOperation\u001b[0m Traceback (most recent call last)", - "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mDecimal\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"inf\"\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;34m-\u001b[0m \u001b[0mDecimal\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"inf\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", + "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mDecimal\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"inf\"\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;34m-\u001b[0m \u001b[0mDecimal\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"inf\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", "\u001b[0;31mInvalidOperation\u001b[0m: []" ] } @@ -4910,7 +4997,7 @@ }, { "cell_type": "code", - "execution_count": 157, + "execution_count": 160, "metadata": { "slideshow": { "slide_type": "slide" @@ -4934,7 +5021,7 @@ }, { "cell_type": "code", - "execution_count": 158, + "execution_count": 161, "metadata": { "slideshow": { "slide_type": "fragment" @@ -4947,7 +5034,7 @@ "Fraction(1, 3)" ] }, - "execution_count": 158, + "execution_count": 161, "metadata": {}, "output_type": "execute_result" } @@ -4958,7 +5045,7 @@ }, { "cell_type": "code", - "execution_count": 159, + "execution_count": 162, "metadata": { "slideshow": { "slide_type": "-" @@ -4971,7 +5058,7 @@ "Fraction(1, 3)" ] }, - "execution_count": 159, + "execution_count": 162, "metadata": {}, "output_type": "execute_result" } @@ -4982,7 +5069,7 @@ }, { "cell_type": "code", - "execution_count": 160, + "execution_count": 163, "metadata": { "slideshow": { "slide_type": "-" @@ -4995,7 +5082,7 @@ "Fraction(3333333333, 10000000000)" ] }, - "execution_count": 160, + "execution_count": 163, "metadata": {}, "output_type": "execute_result" } @@ -5006,7 +5093,7 @@ }, { "cell_type": "code", - "execution_count": 161, + "execution_count": 164, "metadata": { "slideshow": { "slide_type": "-" @@ -5019,7 +5106,7 @@ "Fraction(3333333333, 10000000000)" ] }, - "execution_count": 161, + "execution_count": 164, "metadata": {}, "output_type": "execute_result" } @@ -5041,7 +5128,7 @@ }, { "cell_type": "code", - "execution_count": 162, + "execution_count": 165, "metadata": { "slideshow": { "slide_type": "slide" @@ -5054,7 +5141,7 @@ "Fraction(3, 2)" ] }, - "execution_count": 162, + "execution_count": 165, "metadata": {}, "output_type": "execute_result" } @@ -5065,7 +5152,7 @@ }, { "cell_type": "code", - "execution_count": 163, + "execution_count": 166, "metadata": { "slideshow": { "slide_type": "-" @@ -5078,7 +5165,7 @@ "Fraction(3, 2)" ] }, - "execution_count": 163, + "execution_count": 166, "metadata": {}, "output_type": "execute_result" } @@ -5100,7 +5187,7 @@ }, { "cell_type": "code", - "execution_count": 164, + "execution_count": 167, "metadata": { "slideshow": { "slide_type": "slide" @@ -5113,7 +5200,7 @@ "Fraction(1, 10)" ] }, - "execution_count": 164, + "execution_count": 167, "metadata": {}, "output_type": "execute_result" } @@ -5135,7 +5222,7 @@ }, { "cell_type": "code", - "execution_count": 165, + "execution_count": 168, "metadata": { "slideshow": { "slide_type": "-" @@ -5148,7 +5235,7 @@ "Fraction(3602879701896397, 36028797018963968)" ] }, - "execution_count": 165, + "execution_count": 168, "metadata": {}, "output_type": "execute_result" } @@ -5170,7 +5257,7 @@ }, { "cell_type": "code", - "execution_count": 166, + "execution_count": 169, "metadata": { "slideshow": { "slide_type": "slide" @@ -5183,7 +5270,7 @@ "Fraction(7, 4)" ] }, - "execution_count": 166, + "execution_count": 169, "metadata": {}, "output_type": "execute_result" } @@ -5194,7 +5281,7 @@ }, { "cell_type": "code", - "execution_count": 167, + "execution_count": 170, "metadata": { "slideshow": { "slide_type": "-" @@ -5207,7 +5294,7 @@ "Fraction(1, 2)" ] }, - "execution_count": 167, + "execution_count": 170, "metadata": {}, "output_type": "execute_result" } @@ -5218,7 +5305,7 @@ }, { "cell_type": "code", - "execution_count": 168, + "execution_count": 171, "metadata": { "slideshow": { "slide_type": "-" @@ -5231,7 +5318,7 @@ "Fraction(1, 1)" ] }, - "execution_count": 168, + "execution_count": 171, "metadata": {}, "output_type": "execute_result" } @@ -5242,7 +5329,7 @@ }, { "cell_type": "code", - "execution_count": 169, + "execution_count": 172, "metadata": { "slideshow": { "slide_type": "-" @@ -5255,7 +5342,7 @@ "Fraction(1, 1)" ] }, - "execution_count": 169, + "execution_count": 172, "metadata": {}, "output_type": "execute_result" } @@ -5277,7 +5364,7 @@ }, { "cell_type": "code", - "execution_count": 170, + "execution_count": 173, "metadata": { "slideshow": { "slide_type": "slide" @@ -5290,7 +5377,7 @@ "0.1" ] }, - "execution_count": 170, + "execution_count": 173, "metadata": {}, "output_type": "execute_result" } @@ -5301,7 +5388,7 @@ }, { "cell_type": "code", - "execution_count": 171, + "execution_count": 174, "metadata": { "slideshow": { "slide_type": "fragment" @@ -5314,7 +5401,7 @@ "'0.10000000000000000555111512312578270211815834045410'" ] }, - "execution_count": 171, + "execution_count": 174, "metadata": {}, "output_type": "execute_result" } @@ -5383,12 +5470,12 @@ "source": [ "`complex` numbers are part of core Python. The simplest way to create one is to write an arithmetic expression with the literal `j` notation for $\\textbf{i}$. The `j` is commonly used in many engineering disciplines instead of the symbol $\\textbf{i}$ from math as $I$ in engineering more often than not means [electric current](https://en.wikipedia.org/wiki/Electric_current).\n", "\n", - "For example, the answer to $x^2 = -1$ can be written in Python as `1j` like below. This creates a `complex` object with value `1j`. The same syntactic rules apply as with the above `e` notation: No spaces are allowed between the number and the `j`, and the number may be any `int` or `float` literal." + "For example, the answer to $x^2 = -1$ can be written in Python as `1j` like below. This creates a `complex` object with value `1j`. The same syntactic rules apply as with the above `e` notation: No spaces are allowed between the number and the `j`. The number may be any `int` or `float` literal; however, it is stored as a `float` internally. So, `complex` numbers suffer from the same imprecision as `float` numbers." ] }, { "cell_type": "code", - "execution_count": 172, + "execution_count": 175, "metadata": { "slideshow": { "slide_type": "slide" @@ -5401,7 +5488,7 @@ }, { "cell_type": "code", - "execution_count": 173, + "execution_count": 176, "metadata": { "slideshow": { "slide_type": "fragment" @@ -5411,10 +5498,10 @@ { "data": { "text/plain": [ - "140218611341648" + "139928697740272" ] }, - "execution_count": 173, + "execution_count": 176, "metadata": {}, "output_type": "execute_result" } @@ -5425,7 +5512,7 @@ }, { "cell_type": "code", - "execution_count": 174, + "execution_count": 177, "metadata": { "slideshow": { "slide_type": "-" @@ -5438,7 +5525,7 @@ "complex" ] }, - "execution_count": 174, + "execution_count": 177, "metadata": {}, "output_type": "execute_result" } @@ -5449,7 +5536,7 @@ }, { "cell_type": "code", - "execution_count": 175, + "execution_count": 178, "metadata": { "slideshow": { "slide_type": "-" @@ -5462,7 +5549,7 @@ "1j" ] }, - "execution_count": 175, + "execution_count": 178, "metadata": {}, "output_type": "execute_result" } @@ -5484,7 +5571,7 @@ }, { "cell_type": "code", - "execution_count": 176, + "execution_count": 179, "metadata": { "slideshow": { "slide_type": "slide" @@ -5497,7 +5584,7 @@ "True" ] }, - "execution_count": 176, + "execution_count": 179, "metadata": {}, "output_type": "execute_result" } @@ -5519,7 +5606,7 @@ }, { "cell_type": "code", - "execution_count": 177, + "execution_count": 180, "metadata": { "slideshow": { "slide_type": "slide" @@ -5532,7 +5619,7 @@ "(2+0.5j)" ] }, - "execution_count": 177, + "execution_count": 180, "metadata": {}, "output_type": "execute_result" } @@ -5554,7 +5641,7 @@ }, { "cell_type": "code", - "execution_count": 178, + "execution_count": 181, "metadata": { "slideshow": { "slide_type": "-" @@ -5567,7 +5654,7 @@ "(2+0.5j)" ] }, - "execution_count": 178, + "execution_count": 181, "metadata": {}, "output_type": "execute_result" } @@ -5578,7 +5665,7 @@ }, { "cell_type": "code", - "execution_count": 179, + "execution_count": 182, "metadata": { "slideshow": { "slide_type": "-" @@ -5591,7 +5678,7 @@ "(2+0j)" ] }, - "execution_count": 179, + "execution_count": 182, "metadata": {}, "output_type": "execute_result" } @@ -5602,7 +5689,7 @@ }, { "cell_type": "code", - "execution_count": 180, + "execution_count": 183, "metadata": { "slideshow": { "slide_type": "skip" @@ -5615,7 +5702,7 @@ "(2+0.5j)" ] }, - "execution_count": 180, + "execution_count": 183, "metadata": {}, "output_type": "execute_result" } @@ -5626,7 +5713,7 @@ }, { "cell_type": "code", - "execution_count": 181, + "execution_count": 184, "metadata": { "slideshow": { "slide_type": "skip" @@ -5639,7 +5726,7 @@ "(2+0.5j)" ] }, - "execution_count": 181, + "execution_count": 184, "metadata": {}, "output_type": "execute_result" } @@ -5661,7 +5748,7 @@ }, { "cell_type": "code", - "execution_count": 182, + "execution_count": 185, "metadata": { "slideshow": { "slide_type": "slide" @@ -5675,7 +5762,7 @@ }, { "cell_type": "code", - "execution_count": 183, + "execution_count": 186, "metadata": { "slideshow": { "slide_type": "fragment" @@ -5688,7 +5775,7 @@ "(4+6j)" ] }, - "execution_count": 183, + "execution_count": 186, "metadata": {}, "output_type": "execute_result" } @@ -5699,7 +5786,7 @@ }, { "cell_type": "code", - "execution_count": 184, + "execution_count": 187, "metadata": { "slideshow": { "slide_type": "-" @@ -5712,85 +5799,13 @@ "(-2-2j)" ] }, - "execution_count": 184, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "c1 - c2" - ] - }, - { - "cell_type": "code", - "execution_count": 185, - "metadata": { - "slideshow": { - "slide_type": "skip" - } - }, - "outputs": [ - { - "data": { - "text/plain": [ - "(40+2j)" - ] - }, - "execution_count": 185, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "c1 + 39" - ] - }, - { - "cell_type": "code", - "execution_count": 186, - "metadata": { - "slideshow": { - "slide_type": "skip" - } - }, - "outputs": [ - { - "data": { - "text/plain": [ - "-4j" - ] - }, - "execution_count": 186, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "3.0 - c2" - ] - }, - { - "cell_type": "code", - "execution_count": 187, - "metadata": { - "slideshow": { - "slide_type": "skip" - } - }, - "outputs": [ - { - "data": { - "text/plain": [ - "(5+10j)" - ] - }, "execution_count": 187, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "5 * c1" + "c1 - c2" ] }, { @@ -5805,7 +5820,7 @@ { "data": { "text/plain": [ - "(0.5+0.6666666666666666j)" + "(40+2j)" ] }, "execution_count": 188, @@ -5813,13 +5828,85 @@ "output_type": "execute_result" } ], + "source": [ + "c1 + 39" + ] + }, + { + "cell_type": "code", + "execution_count": 189, + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "-4j" + ] + }, + "execution_count": 189, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "3.0 - c2" + ] + }, + { + "cell_type": "code", + "execution_count": 190, + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "(5+10j)" + ] + }, + "execution_count": 190, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "5 * c1" + ] + }, + { + "cell_type": "code", + "execution_count": 191, + "metadata": { + "slideshow": { + "slide_type": "skip" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "(0.5+0.6666666666666666j)" + ] + }, + "execution_count": 191, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "c2 / 6" ] }, { "cell_type": "code", - "execution_count": 189, + "execution_count": 192, "metadata": { "slideshow": { "slide_type": "fragment" @@ -5832,7 +5919,7 @@ "(-5+10j)" ] }, - "execution_count": 189, + "execution_count": 192, "metadata": {}, "output_type": "execute_result" } @@ -5843,7 +5930,7 @@ }, { "cell_type": "code", - "execution_count": 190, + "execution_count": 193, "metadata": { "slideshow": { "slide_type": "-" @@ -5856,7 +5943,7 @@ "(0.44+0.08j)" ] }, - "execution_count": 190, + "execution_count": 193, "metadata": {}, "output_type": "execute_result" } @@ -5878,7 +5965,7 @@ }, { "cell_type": "code", - "execution_count": 191, + "execution_count": 194, "metadata": { "slideshow": { "slide_type": "slide" @@ -5891,7 +5978,7 @@ "5.0" ] }, - "execution_count": 191, + "execution_count": 194, "metadata": {}, "output_type": "execute_result" } @@ -5913,7 +6000,7 @@ }, { "cell_type": "code", - "execution_count": 192, + "execution_count": 195, "metadata": { "slideshow": { "slide_type": "fragment" @@ -5926,7 +6013,7 @@ "1.0" ] }, - "execution_count": 192, + "execution_count": 195, "metadata": {}, "output_type": "execute_result" } @@ -5937,7 +6024,7 @@ }, { "cell_type": "code", - "execution_count": 193, + "execution_count": 196, "metadata": { "slideshow": { "slide_type": "-" @@ -5950,7 +6037,7 @@ "2.0" ] }, - "execution_count": 193, + "execution_count": 196, "metadata": {}, "output_type": "execute_result" } @@ -5972,7 +6059,7 @@ }, { "cell_type": "code", - "execution_count": 194, + "execution_count": 197, "metadata": { "slideshow": { "slide_type": "fragment" @@ -5985,7 +6072,7 @@ "(1-2j)" ] }, - "execution_count": 194, + "execution_count": 197, "metadata": {}, "output_type": "execute_result" } @@ -6062,7 +6149,7 @@ "\n", "For the other types, in particular, the `float` type, the implications of their imprecision are discussed in detail above.\n", "\n", - "The abstract concepts behind the four outer-most mathematical sets are part of Python since [PEP 3141](https://www.python.org/dev/peps/pep-3141/) in 2007. The [numbers](https://docs.python.org/3/library/numbers.html) module in the [standard library](https://docs.python.org/3/library/index.html) defines what Pythonistas call the **numeric tower**, a collection of five **[abstract data types](https://en.wikipedia.org/wiki/Abstract_data_type)**, or **abstract base classes** as they are called in Python slang:\n", + "The abstract concepts behind the four outer-most mathematical sets are part of Python since [PEP 3141](https://www.python.org/dev/peps/pep-3141/) in 2007. The [numbers](https://docs.python.org/3/library/numbers.html) module in the [standard library](https://docs.python.org/3/library/index.html) defines what Pythonistas call the **numeric tower**, a collection of five **[abstract data types](https://en.wikipedia.org/wiki/Abstract_data_type)**, or **abstract base classes** as they are called in Python jargon:\n", "\n", "- `numbers.Number`: \"any number\" (cf., [documentation](https://docs.python.org/3/library/numbers.html#numbers.Number))\n", "- `numbers.Complex`: \"all complex numbers\" (cf., [documentation](https://docs.python.org/3/library/numbers.html#numbers.Complex))\n", @@ -6073,7 +6160,7 @@ }, { "cell_type": "code", - "execution_count": 195, + "execution_count": 198, "metadata": { "slideshow": { "slide_type": "slide" @@ -6086,7 +6173,7 @@ }, { "cell_type": "code", - "execution_count": 196, + "execution_count": 199, "metadata": { "slideshow": { "slide_type": "-" @@ -6114,7 +6201,7 @@ " 'abstractmethod']" ] }, - "execution_count": 196, + "execution_count": 199, "metadata": {}, "output_type": "execute_result" } @@ -6140,7 +6227,7 @@ }, { "cell_type": "code", - "execution_count": 197, + "execution_count": 200, "metadata": { "scrolled": true, "slideshow": { @@ -6262,7 +6349,7 @@ }, { "cell_type": "code", - "execution_count": 198, + "execution_count": 201, "metadata": { "slideshow": { "slide_type": "skip" @@ -6429,7 +6516,7 @@ }, { "cell_type": "code", - "execution_count": 199, + "execution_count": 202, "metadata": { "slideshow": { "slide_type": "slide" @@ -6442,7 +6529,7 @@ "True" ] }, - "execution_count": 199, + "execution_count": 202, "metadata": {}, "output_type": "execute_result" } @@ -6453,7 +6540,7 @@ }, { "cell_type": "code", - "execution_count": 200, + "execution_count": 203, "metadata": { "slideshow": { "slide_type": "fragment" @@ -6466,7 +6553,7 @@ "True" ] }, - "execution_count": 200, + "execution_count": 203, "metadata": {}, "output_type": "execute_result" } @@ -6477,7 +6564,7 @@ }, { "cell_type": "code", - "execution_count": 201, + "execution_count": 204, "metadata": { "slideshow": { "slide_type": "-" @@ -6490,7 +6577,7 @@ "True" ] }, - "execution_count": 201, + "execution_count": 204, "metadata": {}, "output_type": "execute_result" } @@ -6501,7 +6588,7 @@ }, { "cell_type": "code", - "execution_count": 202, + "execution_count": 205, "metadata": { "slideshow": { "slide_type": "-" @@ -6514,7 +6601,7 @@ "True" ] }, - "execution_count": 202, + "execution_count": 205, "metadata": {}, "output_type": "execute_result" } @@ -6536,7 +6623,7 @@ }, { "cell_type": "code", - "execution_count": 203, + "execution_count": 206, "metadata": { "slideshow": { "slide_type": "slide" @@ -6549,7 +6636,7 @@ "False" ] }, - "execution_count": 203, + "execution_count": 206, "metadata": {}, "output_type": "execute_result" } @@ -6571,7 +6658,7 @@ }, { "cell_type": "code", - "execution_count": 204, + "execution_count": 207, "metadata": { "slideshow": { "slide_type": "fragment" @@ -6584,7 +6671,7 @@ "True" ] }, - "execution_count": 204, + "execution_count": 207, "metadata": {}, "output_type": "execute_result" } @@ -6595,7 +6682,7 @@ }, { "cell_type": "code", - "execution_count": 205, + "execution_count": 208, "metadata": { "slideshow": { "slide_type": "-" @@ -6608,7 +6695,7 @@ "False" ] }, - "execution_count": 205, + "execution_count": 208, "metadata": {}, "output_type": "execute_result" } @@ -6641,7 +6728,7 @@ }, { "cell_type": "code", - "execution_count": 206, + "execution_count": 209, "metadata": { "slideshow": { "slide_type": "slide" @@ -6654,7 +6741,7 @@ }, { "cell_type": "code", - "execution_count": 207, + "execution_count": 210, "metadata": { "slideshow": { "slide_type": "-" @@ -6667,7 +6754,7 @@ "0" ] }, - "execution_count": 207, + "execution_count": 210, "metadata": {}, "output_type": "execute_result" } @@ -6678,7 +6765,7 @@ }, { "cell_type": "code", - "execution_count": 208, + "execution_count": 211, "metadata": { "slideshow": { "slide_type": "slide" @@ -6703,7 +6790,7 @@ " if not isinstance(n, numbers.Integral):\n", " if isinstance(n, numbers.Real):\n", " if n != math.trunc(n) and strict:\n", - " raise ValueError(\"n is not an integer-like value; it has decimals\")\n", + " raise TypeError(\"n is not an integer-like value; it has decimals\")\n", " n = math.trunc(n)\n", " else:\n", " raise TypeError(\"Factorial is only defined for integers\")\n", @@ -6728,7 +6815,7 @@ }, { "cell_type": "code", - "execution_count": 209, + "execution_count": 212, "metadata": { "slideshow": { "slide_type": "slide" @@ -6741,7 +6828,7 @@ "1" ] }, - "execution_count": 209, + "execution_count": 212, "metadata": {}, "output_type": "execute_result" } @@ -6752,7 +6839,7 @@ }, { "cell_type": "code", - "execution_count": 210, + "execution_count": 213, "metadata": { "slideshow": { "slide_type": "-" @@ -6765,7 +6852,7 @@ "6" ] }, - "execution_count": 210, + "execution_count": 213, "metadata": {}, "output_type": "execute_result" } @@ -6776,7 +6863,7 @@ }, { "cell_type": "code", - "execution_count": 211, + "execution_count": 214, "metadata": { "slideshow": { "slide_type": "fragment" @@ -6789,7 +6876,7 @@ "6" ] }, - "execution_count": 211, + "execution_count": 214, "metadata": {}, "output_type": "execute_result" } @@ -6811,7 +6898,7 @@ }, { "cell_type": "code", - "execution_count": 212, + "execution_count": 215, "metadata": { "slideshow": { "slide_type": "slide" @@ -6819,15 +6906,15 @@ }, "outputs": [ { - "ename": "ValueError", + "ename": "TypeError", "evalue": "n is not an integer-like value; it has decimals", "output_type": "error", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[0;31mValueError\u001b[0m Traceback (most recent call last)", - "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mfactorial\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m3.1\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", - "\u001b[0;32m\u001b[0m in \u001b[0;36mfactorial\u001b[0;34m(n, strict)\u001b[0m\n\u001b[1;32m 16\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0misinstance\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mn\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mnumbers\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mReal\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 17\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mn\u001b[0m \u001b[0;34m!=\u001b[0m \u001b[0mmath\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mtrunc\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mn\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32mand\u001b[0m \u001b[0mstrict\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 18\u001b[0;31m \u001b[0;32mraise\u001b[0m \u001b[0mValueError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"n is not an integer-like value; it has decimals\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 19\u001b[0m \u001b[0mn\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mmath\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mtrunc\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mn\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 20\u001b[0m \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;31mValueError\u001b[0m: n is not an integer-like value; it has decimals" + "\u001b[0;31mTypeError\u001b[0m Traceback (most recent call last)", + "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mfactorial\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m3.1\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", + "\u001b[0;32m\u001b[0m in \u001b[0;36mfactorial\u001b[0;34m(n, strict)\u001b[0m\n\u001b[1;32m 16\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0misinstance\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mn\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mnumbers\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mReal\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 17\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mn\u001b[0m \u001b[0;34m!=\u001b[0m \u001b[0mmath\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mtrunc\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mn\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32mand\u001b[0m \u001b[0mstrict\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 18\u001b[0;31m \u001b[0;32mraise\u001b[0m \u001b[0mTypeError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"n is not an integer-like value; it has decimals\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 19\u001b[0m \u001b[0mn\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mmath\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mtrunc\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mn\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 20\u001b[0m \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;31mTypeError\u001b[0m: n is not an integer-like value; it has decimals" ] } ], @@ -6837,7 +6924,7 @@ }, { "cell_type": "code", - "execution_count": 213, + "execution_count": 216, "metadata": { "slideshow": { "slide_type": "fragment" @@ -6850,7 +6937,7 @@ "6" ] }, - "execution_count": 213, + "execution_count": 216, "metadata": {}, "output_type": "execute_result" } @@ -6872,7 +6959,7 @@ }, { "cell_type": "code", - "execution_count": 214, + "execution_count": 217, "metadata": { "slideshow": { "slide_type": "slide" @@ -6886,8 +6973,8 @@ "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mTypeError\u001b[0m Traceback (most recent call last)", - "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mfactorial\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m1\u001b[0m \u001b[0;34m+\u001b[0m \u001b[0;36m2j\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", - "\u001b[0;32m\u001b[0m in \u001b[0;36mfactorial\u001b[0;34m(n, strict)\u001b[0m\n\u001b[1;32m 19\u001b[0m \u001b[0mn\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mmath\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mtrunc\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mn\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 20\u001b[0m \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 21\u001b[0;31m \u001b[0;32mraise\u001b[0m \u001b[0mTypeError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"Factorial is only defined for integers\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 22\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 23\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mn\u001b[0m \u001b[0;34m<\u001b[0m \u001b[0;36m0\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mfactorial\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m1\u001b[0m \u001b[0;34m+\u001b[0m \u001b[0;36m2j\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", + "\u001b[0;32m\u001b[0m in \u001b[0;36mfactorial\u001b[0;34m(n, strict)\u001b[0m\n\u001b[1;32m 19\u001b[0m \u001b[0mn\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mmath\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mtrunc\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mn\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 20\u001b[0m \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 21\u001b[0;31m \u001b[0;32mraise\u001b[0m \u001b[0mTypeError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"Factorial is only defined for integers\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 22\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 23\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mn\u001b[0m \u001b[0;34m<\u001b[0m \u001b[0;36m0\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0;31mTypeError\u001b[0m: Factorial is only defined for integers" ] } @@ -6924,7 +7011,7 @@ "- `Decimal`: similar to `float` but allows customizing the precision; still inherently imprecise\n", "- `Fraction`: a perfect model for rational numbers (i.e., the set $\\mathbb{Q}$); built on top of the `int` type and therefore inherently precise\n", "\n", - "The important takeaways for the data science practicioner are:\n", + "The *important* takeaways for the data science practitioner are:\n", "\n", "1. **Do not mix** precise and imprecise data types, and\n", "2. actively expect `nan` results when working with `float` numbers as there are no **loud failures**.\n", diff --git a/05_numbers_review_and_exercises.ipynb b/05_numbers_review_and_exercises.ipynb new file mode 100644 index 0000000..4246965 --- /dev/null +++ b/05_numbers_review_and_exercises.ipynb @@ -0,0 +1,722 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "# Chapter 5: Numbers" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Content Review" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Read [Chapter 5](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/05_numbers.ipynb) of the book. Then work through the eighteen review questions." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Essay Questions " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Answer the following questions briefly with *at most* 300 characters per question!" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Q1**: In what way is the **binary representation** of `int` objects *similar* to the **decimal system** taught in elementary school?" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + " " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Q2**: Why may objects of type `bool` be regarded a **numeric type** as well?" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + " " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Q3**: Why is it *inefficient* to store `bool` objects in bits resembling a **hexadecimal representation**?" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + " " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Q4**: Colors are commonly expressed in the **hexadecimal system** in websites (cf., the [HTML](https://en.wikipedia.org/wiki/HTML) and [CSS](https://en.wikipedia.org/wiki/Cascading_Style_Sheets) formats).\n", + "\n", + "For example, $#000000$, $#ff9900$, and $#ffffff$ turn out to be black, orange, and white. The six digits are read in *pairs of two* from left to right, and the *three pairs* correspond to the proportions of red, green, and blue mixed together. They reach from $0_{16} = 0_{10}$ for $0$% to $\\text{ff}_{16} = 255_{10}$ for $100$% (cf., this [article](https://en.wikipedia.org/wiki/RGB_color_model) for an in-depth discussion).\n", + "\n", + "In percent, what are the proportions of red, green, and blue that make up orange? Calculate the three percentages separately! How many **bytes** are needed to encode a color? How many **bits** are that?" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + " " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Q5**: What does it mean for a code fragment to **fail silently**?" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + " " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Q6**: Explain why the mathematical set of all real numbers $\\mathbb{R}$ can only be **approximated** by floating-point numbers on a computer!" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + " " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Q7**: How do we deal with a `float` object's imprecision if we need to **check for equality**?" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + " " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Q8**: What data type, built-in or from the [standard library](https://docs.python.org/3/library/index.html), is best suited to represent the [transcendental numbers](https://en.wikipedia.org/wiki/Transcendental_number) $\\pi$ and $\\text{e}$?" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + " " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Q9**: How can **abstract data types**, for example, as defined in the **numeric tower**, be helpful in enabling **duck typing**?" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + " " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### True / False Questions" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Motivate your answer with *one short* sentence!" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Q10**: The precision of `int` objects depends on how we choose to represent them in memory. For example, using a **hexadecimal representation** gives us $16^8$ digits whereas with a **binary representation** an `int` object can have *at most* $2^8$ digits." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + " " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Q11**: With the built-in [round()](https://docs.python.org/3/library/functions.html#round) function, we obtain a *precise* representation for any `float` object if we can live with *less than* $15$ digits of precision." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + " " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Q12**: As most currencies operate with $2$ or $3$ decimals (e.g., EUR $9.99$), the `float` type's limitation of *at most* $15$ digits is *not* a problem in practice." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + " " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Q13**: The [IEEE 754](https://en.wikipedia.org/wiki/IEEE_754) standard's **special values** provide no benefit in practice as we could always use a **[sentinel](https://en.wikipedia.org/wiki/Sentinel_value)** value (i.e., a \"dummy\"). For example, instead of `nan`, we can always use `0` to indicate a *missing* value." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + " " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Q14**: The following code fragment raises an `InvalidOperation` exception. That is an example of code **failing loudly**.\n", + "```python\n", + "float(\"inf\") + float(\"-inf\")\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + " " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Q15**: Python provides a `scientific` type (e.g., `1.23e4`) that is useful mainly to model problems in the domains of physics or astrophysics." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + " " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Q16**: From a practitioner's point of view, the built-in [format()](https://docs.python.org/3/library/functions.html#format) function does the *same* as the built-in [round()](https://docs.python.org/3/library/functions.html#round) function." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + " " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Q17**: The `Decimal` type from the [decimal](https://docs.python.org/3/library/decimal.html) module in the [standard library](https://docs.python.org/3/library/index.html) allows us to model the set of the real numbers $\\mathbb{R}$ *precisely*." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + " " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Q18**: The `Fraction` type from the [fractions](https://docs.python.org/3/library/fractions.html) module in the [standard library](https://docs.python.org/3/library/index.html) allows us to model the set of the rational numbers $\\mathbb{Q}$ *precisely*." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + " " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Coding Exercises" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Discounting Customer Orders (revisited)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Q11** in [Chapter 2's Review & Exercises](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/02_functions_review_and_exercises.ipynb#Volume-of-a-Sphere) section already revealed that we must consider the effects of the `float` type's imprecision.\n", + "\n", + "This becomes even more important when we deal with numeric data modeling accounting or finance data (cf., [this comment](https://stackoverflow.com/a/24976426) on \"falsehoods programmers believe about money\").\n", + "\n", + "In addition to the *inherent imprecision* of numbers in general, the topic of **[rounding numbers](https://en.wikipedia.org/wiki/Rounding)** is also not as trivial as we might expect! [This article](https://realpython.com/python-rounding/) summarizes everything the data science practitioner needs to know.\n", + "\n", + "In this exercise, we revisit **Q9** from [Chapter 3's Review & Exercises](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/03_conditionals_review_and_exercises.ipynb#Discounting-Customer-Orders) section, and make the `discounted_price()` function work *correctly* for real-life sales data." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Q19.1**: Execute the code cells below! What results would you have *expected*, and why?" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "round(1.5)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "round(2.5)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "round(2.675, 2)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + " " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Q19.2**: The built-in [round()](https://docs.python.org/3/library/functions.html#round) function implements the \"**[round half to even](https://en.wikipedia.org/wiki/Rounding#Round_half_to_even)**\" strategy. Describe in one or two sentences what that means!" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + " " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Q19.3**: For the revised `discounted_price()` function, we have to tackle *two* issues: First, we have to replace the built-in `float` type with a data type that allows us to control the precision. Second, the discounted price should be rounded according to a more human-friendly rounding strategy, namely \"**[round half away from zero](https://en.wikipedia.org/wiki/Rounding#Round_half_away_from_zero)**.\"\n", + "\n", + "Describe in one or two sentences how \"**[round half away from zero](https://en.wikipedia.org/wiki/Rounding#Round_half_away_from_zero)**\" is more in line with how humans think of rounding!" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + " " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Q19.4**: We use the `Decimal` type from the [decimal](https://docs.python.org/3/library/decimal.html) module in the [standard library](https://docs.python.org/3/library/index.html) to tackle *both* issues simultaneously.\n", + "\n", + "Assign `euro` a numeric object such that both `Decimal(\"1.5\")` and `Decimal(\"2.5\")` are rounded to `Decimal(\"2\")` (i.e., no decimal) with the [quantize()](https://docs.python.org/3/library/decimal.html#decimal.Decimal.quantize) method!" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from decimal import Decimal" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "euro = ..." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Decimal(\"1.5\").quantize(...)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Decimal(\"2.5\").quantize(...)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Q19.5**: Obviously, the two preceding code cells still [round half to even](https://en.wikipedia.org/wiki/Rounding#Round_half_to_even).\n", + "\n", + "The [decimal](https://docs.python.org/3/library/decimal.html) module defines a `ROUND_HALF_UP` flag that we can pass as the second argument to the [quantize()](https://docs.python.org/3/library/decimal.html#decimal.Decimal.quantize) method. Then, it [rounds half away from zero](https://en.wikipedia.org/wiki/Rounding#Round_half_away_from_zero).\n", + "\n", + "Add `ROUND_HALF_UP` to the code cells! `Decimal(\"2.5\")` should now be rounded to `Decimal(\"3\")`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from decimal import ROUND_HALF_UP" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Decimal(\"1.5\").quantize(...)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Decimal(\"2.5\").quantize(...)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Q19.6**: Instead of `euro`, define `cents` such that rounding occurs to *two* decimals! `Decimal(\"2.675\")` should now be rounded to `Decimal(\"2.68\")`. Do *not* forget to include the `ROUND_HALF_UP` flag!" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "cents = ..." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Decimal(\"2.675\").quantize(...)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Q19.7**: Re-write the function `discounted_price()` from [Chapter 3's Review & Exercises](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/03_conditionals_review_and_exercises.ipynb#Discounting-Customer-Orders) section!\n", + "\n", + "It takes the *positional* arguments `unit_price` and `quantity` and implements a discount scheme for a line item in a customer order as follows:\n", + "\n", + "- if the unit price is over 100 dollars, grant 10% relative discount\n", + "- if a customer orders more than 10 items, one in every five items is for free\n", + "\n", + "Only one of the two discounts is granted, whichever is better for the customer.\n", + "\n", + "The function then returns the overall price for the line item as a `Decimal` number with a precision of *two* decimals.\n", + "\n", + "Enable **duck typing** by allowing the function to be called with various numeric types as the arguments, in particular, `quantity` may be a non-integer as well: Use an appropriate **abstract data type** from the [numbers](https://docs.python.org/3/library/numbers.html) module in the [standard library](https://docs.python.org/3/library/index.html) to verify the arguments' types and also that they are both positive!\n", + "\n", + "It is considered a *best practice* to only round towards the *end* of the calculations." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import numbers" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def discounted_price(...):\n", + " ...\n", + " ...\n", + " ...\n", + " ...\n", + " ...\n", + " ...\n", + " ...\n", + " ...\n", + " ...\n", + " ...\n", + " ...\n", + " ...\n", + " ...\n", + " ...\n", + " ...\n", + " ...\n", + " ..." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Q19.8**: Execute the code cells below and verify the final price for the following four test cases:\n", + "\n", + "- $7$ smartphones @ $99.00$ USD\n", + "- $3$ workstations @ $999.00$ USD\n", + "- $19$ GPUs @ $879.95$ USD\n", + "- $14$ Raspberry Pis @ $35.00$ USD\n", + "\n", + "The output should now *always* be a `Decimal` number with *two* decimals!" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "discounted_price(99, 7)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "discounted_price(999, 3)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "discounted_price(879.95, 19)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "discounted_price(35, 14)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "This also works if `quantity` is passed in as a `float` type." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "discounted_price(99, 7.0)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Decimals beyond the first two are gracefully discarded (i.e., *without* rounding errors accumulating)." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "discounted_price(99.0001, 7)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The basic input validation ensures that the user of `discounted_price()` does not pass in invalid data. Here, the `\"abc\"` creates a `TypeError`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "discounted_price(\"abc\", 7)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "A `-1` passed in as `unit_price` results in a `ValueError`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "discounted_price(-1, 7)" + ] + } + ], + "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.7.3" + }, + "toc": { + "base_numbering": 1, + "nav_menu": {}, + "number_sections": false, + "sideBar": true, + "skip_h1_title": true, + "title_cell": "Table of Contents", + "title_sidebar": "Contents", + "toc_cell": false, + "toc_position": {}, + "toc_section_display": false, + "toc_window_display": false + } + }, + "nbformat": 4, + "nbformat_minor": 2 +}