Commit cafd7d1a authored by CHAMONT David's avatar CHAMONT David
Browse files

Preparation 1-2-Reminders

parent 9f2cba75
# Prepare yourself for the lessons
The prerequisites for this lesssons are given in `prerequisites.md`, together with links to courses and online tutorials which may help to fill the gaps.
For communication with the teachers and other students, you are asked to connect on this server: `https://discord.gg/KgDmf3zr`. Some more information is given in `chatroom.md`.
As better described in `teaching-material.md`, the material will be made available, progressively, on [this public project](https://gitlab.in2p3.fr/chamont/modernscientificcpp).
The file [`installation.md`](installation.md) try to sum up what to install if you want to run the examples on your machine, with or without notebooks, barebone or through docker (in the later case, additional instructions are found in `docker.md`). You can also, at least at the beginning, simply use http://coliru.stacked-crooked.com/. Finally, if you have an account in the RENATER federation, you may use [JupyterHub@Paris-Saclay](`https://jupyterhub.ijclab.in2p3.fr/`) (see `jupyterhub.md`).
# Prepare yourself for the lessons
The prerequisites for this lesssons are given in `en.prerequisites.md`, together with links to courses and online tutorials which may help to fill the gaps.
For communication with the teachers and other students, you are asked to connect on this server: `https://discord.gg/KgDmf3zr`. Some more information is given in `en.chatroom.md`.
As better described in `en.teaching-material.md`, the material will be made available, progressively, on [this public project](https://gitlab.in2p3.fr/chamont/modernscientificcpp).
The file `en.installation.md` try to sum up what to install if you want to run the examples on your machine, with or without notebooks, barebone or through docker (in the later case, additional instructions are found in `en.docker.md`). You can also, at least at the beginning, simply use http://coliru.stacked-crooked.com/. Finally, if you have an account in the RENATER federation, you may use `https://jupyterhub.ijclab.in2p3.fr/` (see `en.jupyterhub.md`).
# How to use `https://jupyterhub.ijclab.in2p3.fr/`
UNDER WORK.
\ No newline at end of file
# How to use JupyterHub@Paris-Saclay
## Connect
- Start yur internet browser.
- Open `https://jupyterhub.ijclab.in2p3.fr/`.
- Click on `Se connecter`, then authenticate with the Renater federation of identities.
- Click on `Start My Server`
- Here you are.
## Download the course material on the server
- At the "almost top" right corner of the windows, ask for `New`/`Terminal`.
- Get the material : `git clone https://gitlab.in2p3.fr/chamont/modernscientificcpp.git ModernScientificCpp`.
- Go back to your previous brwser window.
## Read the material
Just click on the folders and files.
This diff is collapsed.
{
"cells": [
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"\n",
"# Flaws of floating-point computing\n",
"\n",
"Floating-point numbers can represent a very large range of numbers, from the smallest to the largest, similarly to scientific notation. They are the prefered types for scientific computing. Yet, one must be aware of the many **rounding errors** which are implied. "
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"First, in order to check visually the accuracy of some calculations, let's increase to 18 the output stream precision (this is 6 by default)."
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"slideshow": {
"slide_type": "-"
}
},
"outputs": [],
"source": [
"#include <iostream>\n",
"std::cout.precision(18) ;"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"The floating-point types have a limited number of digits available for their internal representation. Many numbers, such as `1./3.`, cannot be represented exactly:"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"0.333333333333333315\n"
]
}
],
"source": [
"std::cout << (1./3.) << std::endl ;"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"Less intuitive, some very simple numbers (for humans) do not have an exact base-two representation:"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {
"slideshow": {
"slide_type": "-"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"0.100000000000000006\n"
]
}
],
"source": [
"std::cout << 0.1 << std::endl ;"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {
"slideshow": {
"slide_type": "-"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"0x1.999999999999ap-4\n"
]
}
],
"source": [
"#include <iomanip>\n",
"std::cout << std::hexfloat << 0.1 << std::endl ;"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"Some simple operations may amass rounding errors, which complicates comparison of floating-point numbers:"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {
"slideshow": {
"slide_type": "-"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"0x1p+0\n",
"0x1.fffffffffffffp-1\n",
"numbers differ !\n"
]
}
],
"source": [
"double d1 = 1. ;\n",
"double d2 = .1+.1+.1+.1+.1+.1+.1+.1+.1+.1 ;\n",
"\n",
"std::cout << d1 << std::endl ;\n",
"std::cout << d2 << std::endl ;\n",
"\n",
"if (d1==d2)\n",
" { std::cout<<\"numbers are the same\"<<std::endl ; }\n",
"else\n",
" { std::cout<<\"numbers differ !\"<<std::endl ; }"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"## Good old-fashioned practice: epsilon\n",
"\n",
"When comparing some floating point numbers, always allow an epsilon difference."
]
},
{
"cell_type": "code",
"execution_count": 22,
"metadata": {
"slideshow": {
"slide_type": "skip"
}
},
"outputs": [],
"source": [
"#include <cmath>\n",
"#include <limits>"
]
},
{
"cell_type": "code",
"execution_count": 20,
"metadata": {
"slideshow": {
"slide_type": "-"
}
},
"outputs": [],
"source": [
"bool compare( double val1, double val2 )\n",
" {\n",
" double epsilon = std::numeric_limits<double>::epsilon() ;\n",
" return (std::abs(val1-val2)<epsilon) ;\n",
" }"
]
},
{
"cell_type": "code",
"execution_count": 21,
"metadata": {
"slideshow": {
"slide_type": "-"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"numbers are the same\n"
]
}
],
"source": [
"if (compare(1.,.1+.1+.1+.1+.1+.1+.1+.1+.1+.1 ))\n",
" { std::cout<<\"numbers are the same\"<<std::endl ; }\n",
"else\n",
" { std::cout<<\"numbers differ !\"<<std::endl ; }"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"## Good old-fashioned practice: make the precision adjustable"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"The first simplest step is to define a type alias and use it throughout the code:"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {
"slideshow": {
"slide_type": "skip"
}
},
"outputs": [],
"source": [
"#include <iostream>\n",
"#include <cmath>\n",
"#include <limits>"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {
"slideshow": {
"slide_type": "-"
}
},
"outputs": [],
"source": [
"typedef double real ;"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {
"slideshow": {
"slide_type": "-"
}
},
"outputs": [],
"source": [
"bool compare( real val1, real val2 )\n",
" {\n",
" double epsilon = std::numeric_limits<real>::epsilon() ;\n",
" std::cout<<\"(~\"<<epsilon<<\") \" ;\n",
" return (std::abs(val1-val2)<epsilon) ;\n",
" }"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {
"slideshow": {
"slide_type": "-"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"(~2.22045e-16) numbers are the same\n"
]
}
],
"source": [
"if (compare(1.,.1+.1+.1+.1+.1+.1+.1+.1+.1+.1 ))\n",
" { std::cout<<\"numbers are the same\"<<std::endl ; }\n",
"else\n",
" { std::cout<<\"numbers differ !\"<<std::endl ; }"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "skip"
}
},
"source": [
"If you wish to perform the same calculations in single precision, just set `typedef` to `float`, compile and run."
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"## More flexible (but difficult) approach : templates\n",
"\n",
"Make any computing function a template, with the floating type as parameter. This allows to mix different precisions within different steps of a scientific computing application."
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {
"slideshow": {
"slide_type": "-"
}
},
"outputs": [],
"source": [
"template< typename Real >\n",
"bool compare( Real val1, Real val2 )\n",
" {\n",
" double epsilon = std::numeric_limits<Real>::epsilon() ;\n",
" std::cout<<\"(~\"<<epsilon<<\") \" ;\n",
" return (std::abs(val1-val2)<epsilon) ;\n",
" }"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"(~1.19209e-07) numbers are the same\n"
]
}
],
"source": [
"float f1 = 1. ;\n",
"float f2 = .1+.1+.1+.1+.1+.1+.1+.1+.1+.1 ;\n",
"\n",
"if (compare(f1,f2))\n",
" { std::cout<<\"numbers are the same\"<<std::endl ; }\n",
"else\n",
" { std::cout<<\"numbers differ !\"<<std::endl ; }"
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"(~1.19209e-07) numbers differ !\n"
]
}
],
"source": [
"float f1 = 1.f ;\n",
"float f2 = .1f+.1f+.1f+.1f+.1f+.1f+.1f+.1f+.1f+.1f ;\n",
"\n",
"if (compare(f1,f2))\n",
" { std::cout<<\"numbers are the same\"<<std::endl ; }\n",
"else\n",
" { std::cout<<\"numbers differ !\"<<std::endl ; }"
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"(~1.19209e-07) numbers are the same\n"
]
}
],
"source": [
"float f1 = 1.f ;\n",
"float f2 = 10.f*.1f ;\n",
"\n",
"if (compare(f1,f2))\n",
" { std::cout<<\"numbers are the same\"<<std::endl ; }\n",
"else\n",
" { std::cout<<\"numbers differ !\"<<std::endl ; }"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"## Conclusion\n",
"\n",
"Modern C++ will not bring any silver bullet for the rounding problems of floating point computing. You still have to rely on only some old-fashioned good practice, and externals tools that can help to locate greatest errors (CADNA, verificarlo, verrou)."
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"# Questions ?"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "skip"
}
},
"source": [
"## References\n",
"\n",
"* https://www.learncpp.com/cpp-tutorial/floating-point-numbers/\n",
"* [What Every Programmer Should Know About Floating-Point Arithmetic](https://floating-point-gui.de/)\n",
"* [IEEE-754 Floating-Point Conversion](https://babbage.cs.qc.cuny.edu/IEEE-754.old/Decimal.html)"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "skip"
}
},
"source": [
"© *CNRS 2020* \n",
"*This document was created by David Chamont and translated by Olga Abramkina. It is available under the [Licence Creative Commons - Attribution - No commercial use - Shared under the conditions 4.0 International](http://creativecommons.org/licenses/by-nc-sa/4.0/)*"
]
}
],
"metadata": {
"celltoolbar": "Diaporama",
"kernelspec": {
"display_name": "C++17",
"language": "C++17",
"name": "xcpp17"
},
"language_info": {
"codemirror_mode": "text/x-c++src",
"file_extension": ".cpp",
"mimetype": "text/x-c++src",
"name": "c++",
"version": "17"
}
},
"nbformat": 4,
"nbformat_minor": 4
}
{
"cells": [
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"# Objects & classes"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"## Redefinition of a class member function\n",
"\n",
"In the case of simple public inheritance, it is possible to define new member functions in the derived class, as well as to override those defined in the base class:"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"slideshow": {
"slide_type": "skip"
}
},
"outputs": [],
"source": [
"#include<iostream>"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [],
"source": [
"struct Base\n",
" {\n",
" void function1() { std::cout<<\"Base::function1\"<<std::endl ; }\n",
" void function2() { std::cout<<\"Base::function2\"<<std::endl ; }\n",
" } ;"
]