Commit b932f1fd authored by GILLES Sebastien's avatar GILLES Sebastien
Browse files

Object programming TP done.

parent 4c4ae336
......@@ -14,7 +14,7 @@
},
"source": [
"<h1>Table of contents<span class=\"tocSkip\"></span></h1>\n",
"<div class=\"toc\"><ul class=\"toc-item\"><li><span><a href=\"#EXERCICE-17:-transform-struct-PowerOfTwoApprox-into-a-class\" data-toc-modified-id=\"EXERCICE-17:-transform-struct-PowerOfTwoApprox-into-a-class-1\">EXERCICE 17: transform struct <code>PowerOfTwoApprox</code> into a class</a></span></li><li><span><a href=\"#EXERCICE-18:-transform-multiply()-into-a-method-Multiply()-of-PowerOfTwoApprox\" data-toc-modified-id=\"EXERCICE-18:-transform-multiply()-into-a-method-Multiply()-of-PowerOfTwoApprox-2\">EXERCICE 18: transform <code>multiply()</code> into a method <code>Multiply()</code> of <code>PowerOfTwoApprox</code></a></span></li><li><span><a href=\"#EXERCICE-19:-transform-display_power_of_2_approx()-into-a-class\" data-toc-modified-id=\"EXERCICE-19:-transform-display_power_of_2_approx()-into-a-class-3\">EXERCICE 19: transform <code>display_power_of_2_approx()</code> into a class</a></span></li><li><span><a href=\"#EXERCICE-20:-transform-display_sum()-into-a-class\" data-toc-modified-id=\"EXERCICE-20:-transform-display_sum()-into-a-class-4\">EXERCICE 20: transform <code>display_sum()</code> into a class</a></span></li><li><span><a href=\"#EXERCICE-21:-factorize-display-of-error\" data-toc-modified-id=\"EXERCICE-21:-factorize-display-of-error-5\">EXERCICE 21: factorize display of error</a></span></li></ul></div>"
"<div class=\"toc\"><ul class=\"toc-item\"><li><span><a href=\"#EXERCICE-17:-transform-struct-PowerOfTwoApprox-into-a-class\" data-toc-modified-id=\"EXERCICE-17:-transform-struct-PowerOfTwoApprox-into-a-class-1\">EXERCICE 17: transform struct <code>PowerOfTwoApprox</code> into a class</a></span></li><li><span><a href=\"#EXERCICE-18:-transform-multiply()-into-a-method-Multiply()-of-PowerOfTwoApprox\" data-toc-modified-id=\"EXERCICE-18:-transform-multiply()-into-a-method-Multiply()-of-PowerOfTwoApprox-2\">EXERCICE 18: transform <code>multiply()</code> into a method <code>Multiply()</code> of <code>PowerOfTwoApprox</code></a></span></li><li><span><a href=\"#EXERCICE-19:-transform-display_power_of_2_approx()-into-a-class\" data-toc-modified-id=\"EXERCICE-19:-transform-display_power_of_2_approx()-into-a-class-3\">EXERCICE 19: transform <code>display_power_of_2_approx()</code> into a class</a></span></li><li><span><a href=\"#EXERCICE-20:-transform-display_sum()-into-a-class\" data-toc-modified-id=\"EXERCICE-20:-transform-display_sum()-into-a-class-4\">EXERCICE 20: transform <code>display_sum()</code> into a class</a></span></li><li><span><a href=\"#EXERCICE-21:-factorize-computation-and-display-of-error\" data-toc-modified-id=\"EXERCICE-21:-factorize-computation-and-display-of-error-5\">EXERCICE 21: factorize computation and display of error</a></span></li></ul></div>"
]
},
{
......@@ -125,15 +125,15 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"### EXERCICE 21: factorize display of error\n",
"### EXERCICE 21: factorize computation and display of error\n",
"\n",
"Create the `error()` function that calculates and displays the error rate between a real number and its approximation, on an integer scale from 0 to a given maximum index. The input arguments are:\n",
"\n",
"* The number of bits used during the approximation\n",
"* The exact actual number\n",
"* The approximation of this number\n",
"* The maximum error index\n",
"* Optionally strings to enable keeping the exact same output as previously.\n",
"* The resolution (the maximum index against which error is expressed - 100 and 1000 respectively up to now).\n",
"* Ideally strings to enable keeping the exact same output as previously; to achieve this you may need a reminder of [how to convert a number into a string](/notebooks/1-ProceduralProgramming/6-Streams.ipynb#Conversion) (the solution present one of the possible conversion but you may of course choose the other one as well!)\n",
"\n",
"This `error()` function should be called in both `Display()` methods."
]
......@@ -146,13 +146,6 @@
"_This notebook is an adaptation of a lecture prepared and redacted by David Chamont (CNRS) under the terms of the licence [Attribution-NonCommercial-ShareAlike 4.0 International (CC BY-NC-SA 4.0)](http://creativecommons.org/licenses/by-nc-sa/4.0/)_ \n",
"_The present version has been redacted by Sébastien Gilles and Vincent Rouvreau (Inria)_"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
......
%% Cell type:markdown id: tags:
# [Getting started in C++](/) - [Object programming](/notebooks/2-ObjectProgramming/0-main.ipynb) - [TP 6](/notebooks/2-ObjectProgramming/4b-TP.ipynb)
%% Cell type:markdown id: tags:
<h1>Table of contents<span class="tocSkip"></span></h1>
<div class="toc"><ul class="toc-item"><li><span><a href="#EXERCICE-17:-transform-struct-PowerOfTwoApprox-into-a-class" data-toc-modified-id="EXERCICE-17:-transform-struct-PowerOfTwoApprox-into-a-class-1">EXERCICE 17: transform struct <code>PowerOfTwoApprox</code> into a class</a></span></li><li><span><a href="#EXERCICE-18:-transform-multiply()-into-a-method-Multiply()-of-PowerOfTwoApprox" data-toc-modified-id="EXERCICE-18:-transform-multiply()-into-a-method-Multiply()-of-PowerOfTwoApprox-2">EXERCICE 18: transform <code>multiply()</code> into a method <code>Multiply()</code> of <code>PowerOfTwoApprox</code></a></span></li><li><span><a href="#EXERCICE-19:-transform-display_power_of_2_approx()-into-a-class" data-toc-modified-id="EXERCICE-19:-transform-display_power_of_2_approx()-into-a-class-3">EXERCICE 19: transform <code>display_power_of_2_approx()</code> into a class</a></span></li><li><span><a href="#EXERCICE-20:-transform-display_sum()-into-a-class" data-toc-modified-id="EXERCICE-20:-transform-display_sum()-into-a-class-4">EXERCICE 20: transform <code>display_sum()</code> into a class</a></span></li><li><span><a href="#EXERCICE-21:-factorize-display-of-error" data-toc-modified-id="EXERCICE-21:-factorize-display-of-error-5">EXERCICE 21: factorize display of error</a></span></li></ul></div>
<div class="toc"><ul class="toc-item"><li><span><a href="#EXERCICE-17:-transform-struct-PowerOfTwoApprox-into-a-class" data-toc-modified-id="EXERCICE-17:-transform-struct-PowerOfTwoApprox-into-a-class-1">EXERCICE 17: transform struct <code>PowerOfTwoApprox</code> into a class</a></span></li><li><span><a href="#EXERCICE-18:-transform-multiply()-into-a-method-Multiply()-of-PowerOfTwoApprox" data-toc-modified-id="EXERCICE-18:-transform-multiply()-into-a-method-Multiply()-of-PowerOfTwoApprox-2">EXERCICE 18: transform <code>multiply()</code> into a method <code>Multiply()</code> of <code>PowerOfTwoApprox</code></a></span></li><li><span><a href="#EXERCICE-19:-transform-display_power_of_2_approx()-into-a-class" data-toc-modified-id="EXERCICE-19:-transform-display_power_of_2_approx()-into-a-class-3">EXERCICE 19: transform <code>display_power_of_2_approx()</code> into a class</a></span></li><li><span><a href="#EXERCICE-20:-transform-display_sum()-into-a-class" data-toc-modified-id="EXERCICE-20:-transform-display_sum()-into-a-class-4">EXERCICE 20: transform <code>display_sum()</code> into a class</a></span></li><li><span><a href="#EXERCICE-21:-factorize-computation-and-display-of-error" data-toc-modified-id="EXERCICE-21:-factorize-computation-and-display-of-error-5">EXERCICE 21: factorize computation and display of error</a></span></li></ul></div>
%% Cell type:markdown id: tags:
### EXERCICE 17: transform struct `PowerOfTwoApprox` into a class
Make `PowerOfTwoApprox` into a class, with proper encapsulation:
* Both data attributes should be made private.
* Constant accessors will therefore be needed (non-constant ones should not be required here)
Expected output is the same as previously.
%% Cell type:markdown id: tags:
### EXERCICE 18: transform `multiply()` into a method `Multiply()` of `PowerOfTwoApprox`
The method will take as argument only the integer coefficient.
`display_sum()` will of course need also some light rewriting to accomodate that change.
Expected output is the same as previously.
%% Cell type:markdown id: tags:
### EXERCICE 19: transform `display_power_of_2_approx()` into a class
Create a class `TestDisplayPowerOfTwoApprox` which will be in charge of printing the display for the 0.65 and 0.35 values.
Use two methods in this class:
* A public method `Do()` which will call the test for 0.65 and 0.35; this method will take the number of bits as argument.
* A private method `Display()` which will provide the display for a given double value (and will therefore be called twice: once for 0.65 and once for 0.35).
New main should look like:
%% Cell type:code id: tags:
``` C++17
int main(int argc, char** argv)
{
static_cast<void>(argc); // to silence warning about unused argc - don't bother
static_cast<void>(argv); // to silence warning about unused argv - don't bother
TestDisplayPowerOfTwoApprox test_display_approx;
for (int Nbits = 2; Nbits <= 8; Nbits += 2)
test_display_approx.Do(Nbits);
std::cout << std::endl;
for (int Nbits = 1; Nbits <= 8; ++Nbits)
display_sum(Nbits, 0.65, 3515, 0.35, 4832);
return EXIT_SUCCESS;
}
```
%% Cell type:markdown id: tags:
Output will be ordered differently:
````
[With 2 bits]: 0.65 ~ 0.75 (3/2^2) [error = 15/100]
[With 2 bits]: 0.35 ~ 0.375 (3/2^3) [error = 7/100]
[With 4 bits]: 0.65 ~ 0.625 (10/2^4) [error = 4/100]
[With 4 bits]: 0.35 ~ 0.34375 (11/2^5) [error = 2/100]
[With 6 bits]: 0.65 ~ 0.65625 (42/2^6) [error = 1/100]
[With 6 bits]: 0.35 ~ 0.351562 (45/2^7) [error = 0/100]
[With 8 bits]: 0.65 ~ 0.648438 (166/2^8) [error = 0/100]
[With 8 bits]: 0.35 ~ 0.349609 (179/2^9) [error = 0/100]
[With 1 bits]: 0.65 * 3515 + 0.35 * 4832 = 3976 ~ 2965 [error = 254/1000]
[With 2 bits]: 0.65 * 3515 + 0.35 * 4832 = 3976 ~ 4448 [error = 119/1000]
[With 3 bits]: 0.65 * 3515 + 0.35 * 4832 = 3976 ~ 4008 [error = 8/1000]
[With 4 bits]: 0.65 * 3515 + 0.35 * 4832 = 3976 ~ 3857 [error = 30/1000]
[With 5 bits]: 0.65 * 3515 + 0.35 * 4832 = 3976 ~ 3967 [error = 2/1000]
[With 6 bits]: 0.65 * 3515 + 0.35 * 4832 = 3976 ~ 4004 [error = 7/1000]
[With 7 bits]: 0.65 * 3515 + 0.35 * 4832 = 3976 ~ 3977 [error = 0/1000]
[With 8 bits]: 0.65 * 3515 + 0.35 * 4832 = 3976 ~ 3968 [error = 2/1000]
````
%% Cell type:markdown id: tags:
### EXERCICE 20: transform `display_sum()` into a class
Likewise, create a class `TestDisplaySum` which will be in charge of printing the display for 0.65 * 3515 + 0.35 * 4832 with public method `Do()` and private method `Display()`.
%% Cell type:markdown id: tags:
### EXERCICE 21: factorize display of error
### EXERCICE 21: factorize computation and display of error
Create the `error()` function that calculates and displays the error rate between a real number and its approximation, on an integer scale from 0 to a given maximum index. The input arguments are:
* The number of bits used during the approximation
* The exact actual number
* The approximation of this number
* The maximum error index
* Optionally strings to enable keeping the exact same output as previously.
* The resolution (the maximum index against which error is expressed - 100 and 1000 respectively up to now).
* Ideally strings to enable keeping the exact same output as previously; to achieve this you may need a reminder of [how to convert a number into a string](/notebooks/1-ProceduralProgramming/6-Streams.ipynb#Conversion) (the solution present one of the possible conversion but you may of course choose the other one as well!)
This `error()` function should be called in both `Display()` methods.
%% Cell type:markdown id: tags:
© _CNRS 2016_ - _Inria 2018_
_This notebook is an adaptation of a lecture prepared and redacted by David Chamont (CNRS) under the terms of the licence [Attribution-NonCommercial-ShareAlike 4.0 International (CC BY-NC-SA 4.0)](http://creativecommons.org/licenses/by-nc-sa/4.0/)_
_The present version has been redacted by Sébastien Gilles and Vincent Rouvreau (Inria)_
%% Cell type:code id: tags:
``` C++17
```
......
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# [Getting started in C++](/) - [Object programming](/notebooks/2-ObjectProgramming/0-main.ipynb) - [TP 7](/notebooks/2-ObjectProgramming/6b-TP.ipynb)"
]
},
{
"cell_type": "markdown",
"metadata": {
"toc": true
},
"source": [
"<h1>Table of contents<span class=\"tocSkip\"></span></h1>\n",
"<div class=\"toc\"><ul class=\"toc-item\"><li><span><a href=\"#EXERCICE-22:-base-class-TestDisplay\" data-toc-modified-id=\"EXERCICE-22:-base-class-TestDisplay-1\">EXERCICE 22: base class <code>TestDisplay</code></a></span></li><li><span><a href=\"#EXERCICE-23:-inherit-from-TestDisplayPowerOfTwoApprox\" data-toc-modified-id=\"EXERCICE-23:-inherit-from-TestDisplayPowerOfTwoApprox-2\">EXERCICE 23: inherit from <code>TestDisplayPowerOfTwoApprox</code></a></span></li><li><span><a href=\"#EXERCICE-24:-loop()-function\" data-toc-modified-id=\"EXERCICE-24:-loop()-function-3\">EXERCICE 24: loop() function</a></span></li><li><span><a href=\"#EXERCICE-25:-make-loop()-a-class\" data-toc-modified-id=\"EXERCICE-25:-make-loop()-a-class-4\">EXERCICE 25: make <code>loop()</code> a class</a></span></li><li><span><a href=\"#EXERCICE-26:-store-TestDisplay-objects-in-Loop\" data-toc-modified-id=\"EXERCICE-26:-store-TestDisplay-objects-in-Loop-5\">EXERCICE 26: store <code>TestDisplay</code> objects in <code>Loop</code></a></span></li><li><span><a href=\"#EXERCICE-27:-simplification\" data-toc-modified-id=\"EXERCICE-27:-simplification-6\">EXERCICE 27: simplification</a></span></li><li><span><a href=\"#EXERCICE-28:-dynamic-allocation-of-array\" data-toc-modified-id=\"EXERCICE-28:-dynamic-allocation-of-array-7\">EXERCICE 28: dynamic allocation of array</a></span></li><li><span><a href=\"#EXERCICE-29:-move-ownership-into-Loop\" data-toc-modified-id=\"EXERCICE-29:-move-ownership-into-Loop-8\">EXERCICE 29: move ownership into <code>Loop</code></a></span></li><li><span><a href=\"#EXERCICE-30:-transform-Loop-into-TestDisplayContainer\" data-toc-modified-id=\"EXERCICE-30:-transform-Loop-into-TestDisplayContainer-9\">EXERCICE 30: transform <code>Loop</code> into <code>TestDisplayContainer</code></a></span></li></ul></div>"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### EXERCICE 22: base class `TestDisplay`\n",
"\n",
"Create a base class `TestDisplay` from which both `TestDisplayPowerOfTwoApprox` and `TestDisplaySum` will inherit publicly.\n",
"\n",
"This class:\n",
"\n",
"* Should get a constructor which sets the resolution.\n",
"* Includes a protected method named `PrintNumericalError()` that will replace the `print_numerical_error()` we introduced in previous exercice.\n",
"\n",
"The constructors of derived classes will of course have to be modified accordingly: so far we relied on default ones."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### EXERCICE 23: inherit from `TestDisplayPowerOfTwoApprox`\n",
"\n",
"We would like to get back former output in which we got first all outputs for 0.65, then all the ones for 0.35.\n",
"\n",
"To do so, we will create two classes `TestDisplayPowerOfTwoApprox065` and `TestDisplayPowerOfTwoApprox035` that inherits from `TestDisplayPowerOfTwoApprox`.\n",
"\n",
"Of course, we still abide by the DRY principle and we want to specialize only the code related to `Do()` method. \n",
"\n",
"The `main()` to use:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"int main(int argc, char** argv)\n",
"{\n",
" static_cast<void>(argc); // to silence warning about unused argc - don't bother \n",
" static_cast<void>(argv); // to silence warning about unused argv - don't bother \n",
"\n",
" TestDisplayPowerOfTwoApprox065 test_display_approx065(100); \n",
"\n",
" for (int Nbits = 2; Nbits <= 8; Nbits += 2)\n",
" test_display_approx065.Do(Nbits); \n",
"\n",
" std::cout << std::endl;\n",
" \n",
" TestDisplayPowerOfTwoApprox035 test_display_approx035(100); \n",
"\n",
" for (int Nbits = 2; Nbits <= 8; Nbits += 2)\n",
" test_display_approx035.Do(Nbits); \n",
" \n",
" std::cout << std::endl;\n",
"\n",
" TestDisplaySum test_display_sum(1000);\n",
"\n",
" for (int Nbits = 1; Nbits <= 8; ++Nbits)\n",
" test_display_sum.Do(Nbits);\n",
"\n",
" return EXIT_SUCCESS;\n",
"}"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"_Expected output:_\n",
"\n",
"````\n",
"[With 2 bits]: 0.65 ~ 0.75 (3 / 2^2) [error = 15/100]\n",
"[With 4 bits]: 0.65 ~ 0.625 (10 / 2^4) [error = 4/100]\n",
"[With 6 bits]: 0.65 ~ 0.65625 (42 / 2^6) [error = 1/100]\n",
"[With 8 bits]: 0.65 ~ 0.648438 (166 / 2^8) [error = 0/100]\n",
"\n",
"[With 2 bits]: 0.35 ~ 0.375 (3 / 2^3) [error = 7/100]\n",
"[With 4 bits]: 0.35 ~ 0.34375 (11 / 2^5) [error = 2/100]\n",
"[With 6 bits]: 0.35 ~ 0.351562 (45 / 2^7) [error = 0/100]\n",
"[With 8 bits]: 0.35 ~ 0.349609 (179 / 2^9) [error = 0/100]\n",
"\n",
"[With 1 bits]: 0.65 * 3515 + 0.35 * 4832 = 3976 ~ 2965 [error = 254/1000]\n",
"[With 2 bits]: 0.65 * 3515 + 0.35 * 4832 = 3976 ~ 4448 [error = 119/1000]\n",
"[With 3 bits]: 0.65 * 3515 + 0.35 * 4832 = 3976 ~ 4008 [error = 8/1000]\n",
"[With 4 bits]: 0.65 * 3515 + 0.35 * 4832 = 3976 ~ 3857 [error = 30/1000]\n",
"[With 5 bits]: 0.65 * 3515 + 0.35 * 4832 = 3976 ~ 3967 [error = 2/1000]\n",
"[With 6 bits]: 0.65 * 3515 + 0.35 * 4832 = 3976 ~ 4004 [error = 7/1000]\n",
"[With 7 bits]: 0.65 * 3515 + 0.35 * 4832 = 3976 ~ 3977 [error = 0/1000]\n",
"[With 8 bits]: 0.65 * 3515 + 0.35 * 4832 = 3976 ~ 3968 [error = 2/1000]\n",
"````"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### EXERCICE 24: loop() function\n",
"\n",
"Create a `loop()` function which takes as arguments:\n",
"\n",
"* Minimum maximum number of bits to consider.\n",
"* Increment over the number of bits\n",
"* Maximum maximum number of bits to consider.\n",
"* The resolution.\n",
"* A `TestDisplay` object (per reference).\n",
"\n",
"The `main()` should now be:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"int main(int argc, char** argv)\n",
"{\n",
" static_cast<void>(argc); // to silence warning about unused argc - don't bother \n",
" static_cast<void>(argv); // to silence warning about unused argv - don't bother \n",
" \n",
" TestDisplayPowerOfTwoApprox065 test_display_approx065(100); \n",
" TestDisplayPowerOfTwoApprox035 test_display_approx035(100); \n",
" TestDisplaySum test_display_sum(1000);\n",
" \n",
" loop(2, 8, 2, test_display_approx065);\n",
" loop(2, 8, 2, test_display_approx035);\n",
" loop(1, 8, 1, test_display_sum); \n",
"\n",
" return EXIT_SUCCESS;\n",
"}"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"To do so, you will need to define `Do()` as a virtual method in `TestDisplay()`. As `TestDisplay` is not meant to be instantiated directly, make sure to make this class pure virtual.\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### EXERCICE 25: make `loop()` a class\n",
"\n",
"Replace `loop()` by a class `Loop` with a method `Do()` which is called."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### EXERCICE 26: store `TestDisplay` objects in `Loop`\n",
"\n",
"Add to the `Loop` class:\n",
"\n",
"* A data attribute to store 5 `TestDisplay` objects: `TestDisplay* test_display_list_[5]`. We will store them as pointers for two reasons:\n",
" * There are no default constructor for `TestDisplay`, so the compiler would have yelled.\n",
" * We want polymorphism to be put in motion, and it requires either pointers or references.\n",
"* A method to register an array in this internal array, with prototype:\n",
"\n",
"````\n",
"void Register(int position, TestDisplay test_display);\n",
"````\n",
"\n",
"where `position` is the index at which `test_display` will be stored. This function should of course check `position` is valid; if not use the following function:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"[[noreturn]] void error(std::string explanation)\n",
"{\n",
" std::cout << \"ERROR: \" << explanation << std::endl;\n",
" exit(EXIT_FAILURE);\n",
"}"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"`Loop::Do()` won't take any longer a `TestDisplay` argument but instead act upon all the ones stored in the data attribute; if nullptr is found for an object it will be skipped (so don't forget to correctly set them initially to this value!)\n",
"\n",
"`main()` to use is: "
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"int main(int argc, char** argv)\n",
"{\n",
" static_cast<void>(argc); // to silence warning about unused argc - don't bother \n",
" static_cast<void>(argv); // to silence warning about unused argv - don't bother \n",
" \n",
" TestDisplayPowerOfTwoApprox065 test_display_approx065(100); \n",
" TestDisplayPowerOfTwoApprox035 test_display_approx035(100); \n",
" TestDisplaySum test_display_sum(1000);\n",
" \n",
" Loop loop;\n",
" loop.Register(0, &test_display_approx065);\n",
" loop.Register(1, &test_display_approx035);\n",
" loop.Register(3, &test_display_sum);\n",
" \n",
" loop.Do(4, 16, 4);\n",
"\n",
" return EXIT_SUCCESS;\n",
"}"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Output is modified: with current code we impose same bit range for all `TestDisplay`:"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"````\n",
"[With 4 bits]: 0.65 ~ 0.625 (10/2^4) [error = 38462/1000000]\n",
"[With 8 bits]: 0.65 ~ 0.648438 (166/2^8) [error = 2404/1000000]\n",
"[With 12 bits]: 0.65 ~ 0.649902 (2662/2^12) [error = 150/1000000]\n",
"[With 16 bits]: 0.65 ~ 0.649994 (42598/2^16) [error = 9/1000000]\n",
"\n",
"[With 4 bits]: 0.35 ~ 0.34375 (11/2^5) [error = 17857/1000000]\n",
"[With 8 bits]: 0.35 ~ 0.349609 (179/2^9) [error = 1116/1000000]\n",
"[With 12 bits]: 0.35 ~ 0.349976 (2867/2^13) [error = 70/1000000]\n",
"[With 16 bits]: 0.35 ~ 0.349998 (45875/2^17) [error = 4/1000000]\n",
"\n",
"[With 4 bits]: 0.65 * 3515 + 0.35 * 4832 = 3976 ~ 3857 [error = 29930/1000000]\n",
"[With 8 bits]: 0.65 * 3515 + 0.35 * 4832 = 3976 ~ 3968 [error = 2012/1000000]\n",
"[With 12 bits]: 0.65 * 3515 + 0.35 * 4832 = 3976 ~ 3975 [error = 252/1000000]\n",
"[With 16 bits]: 0.65 * 3515 + 0.35 * 4832 = 3976 ~ 3975 [error = 252/1000000]\n",
"````\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### EXERCICE 27: simplification\n",
"\n",
"Let's face it: the possibility to place the `TestDisplay` where we want is a bit overkill: we just need to iterate through all objects and don't really need to know the exact position of each of them.\n",
"\n",
"So we will:\n",
"\n",
"* Remove the position argument; each new `TestDisplay` object registered is added to the first position available.\n",
"* A new data attribute `next_position_available_` will tell which is not yet used.\n",
"* The error handling will now check `next_position_available_` has not reached 5 when a new `Register()` call is done.\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### EXERCICE 28: dynamic allocation of array\n",
"\n",
"Instead of setting an arbitrary size of 5, we will now add a size dynamically in `Loop` constructor; the internal storage will now be:\n",
"\n",
"````\n",
"TestDisplay** test_display_list_;\n",
"````\n",
"\n",
"meaning we will store an array of pointers (don't worry, we will see later how to avoid such monstruosities... but it is useful nonetheless to try them a bit).\n",
"\n",
"Constructor must now:\n",
"\n",
"* Allocate the array of `TestDisplay*` with a size given as its argument.\n",
"* Keep track of the size (the related data attribute should be constant: we don't intend to modify the size of the array after construction).\n",
"* Set each element to `nullptr`.\n",
"\n",
"Destructor must of course take care of deallocating properly the memory.\n",
"\n",
"**NOTE:** To avoid a warning you should use `std::size_t` when allocating the array: this is the type used for array (which is in all compilers I've used an alias to `unsigned long`)."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### EXERCICE 29: move ownership into `Loop`\n",
"\n",
"Currently `Loop` use pointers to underlying `TestDisplay` objects but do not own them: it is not in charge of deallocating them. This may prove dangerous in a more complicated program than this one; we will now change this so that `Loop` gain ownership over the content.\n",
"\n",
"Of course, we should make sure they are properly deallocated at destruction.\n",
"\n",
"New main will be:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"int main(int argc, char** argv)\n",
"{\n",
" static_cast<void>(argc); // to silence warning about unused argc - don't bother \n",
" static_cast<void>(argv); // to silence warning about unused argv - don't bother \n",
" \n",
" Loop loop(3);\n",
" loop.Register(new TestDisplayPowerOfTwoApprox065(1000000));\n",
" loop.Register(new TestDisplayPowerOfTwoApprox035(1000000));\n",
" loop.Register(new TestDisplaySum(1000000));\n",
" \n",
" loop.Do(4, 16, 4);\n",
"\n",
" return EXIT_SUCCESS;\n",
"}"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### EXERCICE 30: transform `Loop` into `TestDisplayContainer`\n",
"\n",
"Once again we probably went a bridge too far: it is useful to provide an object which contains several `TestDisplay` together, but making it take in charge the loop might not be that good an idea (in a real program you might for instance interact with this container by another mean than the pre-defined loop).\n",
"\n",
"We will therefore rename the class `Loop` `TestDisplayContainer`, and reintroduce a `loop()` function that will interact with it. The `main()` is now:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"int main(int argc, char** argv)\n",
"{\n",
" static_cast<void>(argc); // to silence warning about unused argc - don't bother \n",
" static_cast<void>(argv); // to silence warning about unused argv - don't bother \n",
" \n",
" TestDisplayContainer container(3);\n",
" container.Register(new TestDisplayPowerOfTwoApprox065(1000000));\n",
" container.Register(new TestDisplayPowerOfTwoApprox035(1000000));\n",
" container.Register(new TestDisplaySum(1000000));\n",
" \n",
" loop(4, 16, 4, container);\n",
"\n",
" return EXIT_SUCCESS;\n",
"}"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We will need to define two methods for `TestDisplayContainer`:\n",
"\n",
"* A method `Nelement()` which returns the number of elements.\n",
"* A method `GetElement(int i)` which returns the i-th element (and provide an error if i is invalid)."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n",
"© _CNRS 2016_ - _Inria 2018_ \n",
"_This notebook is an adaptation of a lecture prepared and redacted by David Chamont (CNRS) under the terms of the licence [Attribution-NonCommercial-ShareAlike 4.0 International (CC BY-NC-SA 4.0)](http://creativecommons.org/licenses/by-nc-sa/4.0/)_ \n",
"_The present version has been redacted by Sébastien Gilles and Vincent Rouvreau (Inria)_"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "C++17",
"language": "C++17",
"name": "xeus-cling-cpp17"
},
"language_info": {
"codemirror_mode": "text/x-c++src",
"file_extension": ".cpp",
"mimetype": "text/x-c++src",
"name": "c++",
"version": "-std=c++17"
},
"latex_envs": {
"LaTeX_envs_menu_present": true,
"autoclose": false,
"autocomplete": true,
"bibliofile": "biblio.bib",
"cite_by": "apalike",
"current_citInitial": 1,
"eqLabelWithNumbers": true,
"eqNumInitial": 1,
"hotkeys": {
"equation": "Ctrl-E",
"itemize": "Ctrl-I"
},
"labels_anchors": false,
"latex_user_defs": false,
"report_style_numbering": false,
"user_envs_cfg": false
},
"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": true,
"toc_position": {},
"toc_section_display": true,
"toc_window_display": true
}
},
"nbformat": 4,
"nbformat_minor": 2
}
%% Cell type:markdown id: tags:
# [Getting started in C++](/) - [Object programming](/notebooks/2-ObjectProgramming/0-main.ipynb) - [TP 7](/notebooks/2-ObjectProgramming/6b-TP.ipynb)
%% Cell type:markdown id: tags:
<h1>Table of contents<span class="tocSkip"></span></h1>
<div class="toc"><ul class="toc-item"><li><span><a href="#EXERCICE-22:-base-class-TestDisplay" data-toc-modified-id="EXERCICE-22:-base-class-TestDisplay-1">EXERCICE 22: base class <code>TestDisplay</code></a></span></li><li><span><a href="#EXERCICE-23:-inherit-from-TestDisplayPowerOfTwoApprox" data-toc-modified-id="EXERCICE-23:-inherit-from-TestDisplayPowerOfTwoApprox-2">EXERCICE 23: inherit from <code>TestDisplayPowerOfTwoApprox</code></a></span></li><li><span><a href="#EXERCICE-24:-loop()-function" data-toc-modified-id="EXERCICE-24:-loop()-function-3">EXERCICE 24: loop() function</a></span></li><li><span><a href="#EXERCICE-25:-make-loop()-a-class" data-toc-modified-id="EXERCICE-25:-make-loop()-a-class-4">EXERCICE 25: make <code>loop()</code> a class</a></span></li><li><span><a href="#EXERCICE-26:-store-TestDisplay-objects-in-Loop" data-toc-modified-id="EXERCICE-26:-store-TestDisplay-objects-in-Loop-5">EXERCICE 26: store <code>TestDisplay</code> objects in <code>Loop</code></a></span></li><li><span><a href="#EXERCICE-27:-simplification" data-toc-modified-id="EXERCICE-27:-simplification-6">EXERCICE 27: simplification</a></span></li><li><span><a href="#EXERCICE-28:-dynamic-allocation-of-array" data-toc-modified-id="EXERCICE-28:-dynamic-allocation-of-array-7">EXERCICE 28: dynamic allocation of array</a></span></li><li><span><a href="#EXERCICE-29:-move-ownership-into-Loop" data-toc-modified-id="EXERCICE-29:-move-ownership-into-Loop-8">EXERCICE 29: move ownership into <code>Loop</code></a></span></li><li><span><a href="#EXERCICE-30:-transform-Loop-into-TestDisplayContainer" data-toc-modified-id="EXERCICE-30:-transform-Loop-into-TestDisplayContainer-9">EXERCICE 30: transform <code>Loop</code> into <code>TestDisplayContainer</code></a></span></li></ul></div>
%% Cell type:markdown id: tags:
### EXERCICE 22: base class `TestDisplay`
Create a base class `TestDisplay` from which both `TestDisplayPowerOfTwoApprox` and `TestDisplaySum` will inherit publicly.
This class:
* Should get a constructor which sets the resolution.
* Includes a protected method named `PrintNumericalError()` that will replace the `print_numerical_error()` we introduced in previous exercice.
The constructors of derived classes will of course have to be modified accordingly: so far we relied on default ones.
%% Cell type:markdown id: tags:
### EXERCICE 23: inherit from `TestDisplayPowerOfTwoApprox`
We would like to get back former output in which we got first all outputs for 0.65, then all the ones for 0.35.
To do so, we will create two classes `TestDisplayPowerOfTwoApprox065` and `TestDisplayPowerOfTwoApprox035` that inherits from `TestDisplayPowerOfTwoApprox`.
Of course, we still abide by the DRY principle and we want to specialize only the code related to `Do()` method.
The `main()` to use:
%% Cell type:code id: tags:
``` C++17
int main(int argc, char** argv)
{
static_cast<void>(argc); // to silence warning about unused argc - don't bother
static_cast<void>(argv); // to silence warning about unused argv - don't bother
TestDisplayPowerOfTwoApprox065 test_display_approx065(100);
for (int Nbits = 2; Nbits <= 8; Nbits += 2)
test_display_approx065.Do(Nbits);
std::cout << std::endl;
TestDisplayPowerOfTwoApprox035 test_display_approx035(100);
for (int Nbits = 2; Nbits <= 8; Nbits += 2)
test_display_approx035.Do(Nbits);
std::cout << std::endl;
TestDisplaySum test_display_sum(1000);
for (int Nbits = 1; Nbits <= 8; ++Nbits)
test_display_sum.Do(Nbits);
return EXIT_SUCCESS;
}
```
%% Cell type:markdown id: tags:
_Expected output:_
````
[With 2 bits]: 0.65 ~ 0.75 (3 / 2^2) [error = 15/100]
[With 4 bits]: 0.65 ~ 0.625 (10 / 2^4) [error = 4/100]
[With 6 bits]: 0.65 ~ 0.65625 (42 / 2^6) [error = 1/100]
[With 8 bits]: 0.65 ~ 0.648438 (166 / 2^8) [error = 0/100]
[With 2 bits]: 0.35 ~ 0.375 (3 / 2^3) [error = 7/100]
[With 4 bits]: 0.35 ~ 0.34375 (11 / 2^5) [error = 2/100]
[With 6 bits]: 0.35 ~ 0.351562 (45 / 2^7) [error = 0/100]
[With 8 bits]: 0.35 ~ 0.349609 (179 / 2^9) [error = 0/100]
[With 1 bits]: 0.65 * 3515 + 0.35 * 4832 = 3976 ~ 2965 [error = 254/1000]
[With 2 bits]: 0.65 * 3515 + 0.35 * 4832 = 3976 ~ 4448 [error = 119/1000]
[With 3 bits]: 0.65 * 3515 + 0.35 * 4832 = 3976 ~ 4008 [error = 8/1000]
[With 4 bits]: 0.65 * 3515 + 0.35 * 4832 = 3976 ~ 3857 [error = 30/1000]
[With 5 bits]: 0.65 * 3515 + 0.35 * 4832 = 3976 ~ 3967 [error = 2/1000]
[With 6 bits]: 0.65 * 3515 + 0.35 * 4832 = 3976 ~ 4004 [error = 7/1000]
[With 7 bits]: 0.65 * 3515 + 0.35 * 4832 = 3976 ~ 3977 [error = 0/1000]
[With 8 bits]: 0.65 * 3515 + 0.35 * 4832 = 3976 ~ 3968 [error = 2/1000]
````
%% Cell type:markdown id: tags:
### EXERCICE 24: loop() function
Create a `loop()` function which takes as arguments:
* Minimum maximum number of bits to consider.
* Increment over the number of bits
* Maximum maximum number of bits to consider.
* The resolution.
* A `TestDisplay` object (per reference).
The `main()` should now be:
%% Cell type:code id: tags:
``` C++17
int main(int argc, char** argv)
{
static_cast<void>(argc); // to silence warning about unused argc - don't bother
static_cast<void>(argv); // to silence warning about unused argv - don't bother