Commit 2afc9a26 authored by Praetorius, Simon's avatar Praetorius, Simon
Browse files

Add chapter about blocks and scopes, operators and functions to presentation and lecture notes

parent 0397adb7
......@@ -4,7 +4,7 @@
| Topic | Download | Updated |
|----------------------------------------|--------------------------|---------------|
| Scientific Programming with C++ | [lecture.pdf][] | 2021/04/10 |
| Scientific Programming with C++ | [lecture.pdf][] | 2021/04/20 |
[lecture.pdf]: https://gitlab.mn.tu-dresden.de/teaching/scprog/so2021/-/jobs/artifacts/master/raw/lecture/lecture.pdf?job=build
......@@ -20,6 +20,17 @@ to the tutorial project. The submission procedure is described there. Please rea
instructions carefully. Ask the tutor (@spraetor) if you have any further questions.
### Cloning
We manage certain large files, like PDFs or images that are needed in
order to build the lecture, with [git-lfs]. Before cloning this
repository, make sure that `git-lfs` is installed and configured
properly. Enabling it globally is as easy as `git-lfs install`; see
git-lfs' [homepage][git-lfs] for more information.
[git-lfs]: https://git-lfs.github.com/
## More reading
Online references and literature useful for completing the exercises are listed below:
......
\section{Operators\label{sec:operator}}
We have see already in the initial example the usage of arithmetic and many other \emph{operators}. Operators are special functions with typically prefix-notation (for unary operators) and infix notation (for binary operators) and are written with the classical mathematical symbols. In the initial example, we had \texttt{+, -, *, ::, ., <<, = , ",", ()}.
\begin{defn}
We call operators acting on one operand \emph{unary operators} (like \texttt{-, *, \&}), acting on two operands \emph{binary operator} (like \texttt{+, -, *, /, =, +=, ...}) and even acting on three operands a \emph{ternary operators} (there is only \texttt{?:}).
\end{defn}
Operators are characterized by its properties: \emph{associativity}, \emph{precedence}, and whether they can be \emph{overloaded}.
% -------------------------------------------------------------------------------------------------
\subsection{Associativity\label{sec:operator-associativity}}
\begin{defn}
Operator associativity means the property of an operator determining the order in which to evaluate multiple occurrences of this operator in an expression without changing the result of the evaluation.
\end{defn}
Only in \emph{associative compositions} the result depends on the associativity. In order to fix the meaning of expressions with multiple
similar operators without brackets we introduce the convention
\begin{itemize}
\item A \emph{left-associative operator} is evaluated from left to right.
\item A \emph{right-associative operator} is evaluated from right to left.
\end{itemize}
All (binary) operators are classified as left or right associative
\begin{example}
Binary arithmetic operations are \emph{left-associative}: (\texttt{+, -, *, /, \%, <, >, \&\&, ||})
\cpp{a + b + c} is equivalent to \cpp{(a + b) + c}
\end{example}
\begin{example}
Assignment operators are \emph{right-associative}: (\texttt{=, +=, <<=, ...}), \ie the expression
\cpp{x= y= z} is evaluated from right to left and thus equivalent to: \cpp{x= (y= z)}
\end{example}
% -------------------------------------------------------------------------------------------------
\subsection{Precedence\label{sec:operator-precedence}}
Operators are ordered by its precedence. This defines a \emph{partial ordering} of the operators and specified which operators is evaluated first. The precedence can be overridden using brackets.
From basic arithmetics you know the precedence of some arithmetic operators, especially \texttt{+, -, *, /}. This precedence is known in some countries as mnemonics:
\begin{itemize}
\item Germany: \textit{Punktrechnung geht vor Strichrechnung}, meaning Multiplication/Division before Addition/Subtraction
\item United States: \textbf{PEMDAS}: Parentheses, Exponents, Multiplication/Division, Addition/Subtraction. PEMDAS is often expanded to the mnemonic ``\textit{Please Excuse My Dear Aunt Sally}''.
\item Canada and New Zealand: \textbf{BEDMAS}: Brackets, Exponents, Division/Multiplication, Addition/Subtraction.
\item UK, Pakistan, India, Bangladesh and Australia and some other English-speaking countries: \textbf{BODMAS}: Brackets, Order, Division/Multiplication, Addition/Subtraction or Brackets, Of/Division/Multiplication, Addition/Subtraction.
\end{itemize}
\begin{example}
An example with classical mathematical operators on integers:
\[\begin{split}
x &= 2 * 2 + 2\, /\, 2 - 2\quad\Rightarrow\quad x = \left(\left(\left(2 * 2\right) + \left(2 / 2\right)\right) - 2\right) = 3 \\
y &= 8 / 2 * (2 + 2)\quad\Rightarrow\quad y = (8 / 2) * (2 + 2) = 16
\end{split}\]
\end{example}
\begin{rem}
The operator \cpp{^} does not mean exponentiation or power, but the logical X-Or. In Matlab/Octave this operator has the expected meaning, but in C++ the operator has a different precedence than the power operator would have from a mathematical perspective.
This means:
\cppline{a = b^2 + c}
is equivalent to
\cppline{a = b^(2 + c)}
BUT NOT TO
\cppline{a = (b^2) + c}
There is no power operator in C++! You have to call the function \cpp{std::pow} instead.
\end{rem}
\begin{guideline}{Principle}
When in doubt or to clarify the expression: use parentheses.
\end{guideline}
% -------------------------------------------------------------------------------------------------
\subsection{Examples of operators}
In the table below, the operators are ordered by precedence and information about associativity is given. Here I give you a summary of most of the operators and its meaning. Most of the operators are defined for arithmetic types (integers or floating-point numbers), but some are also defined for library types, like \cpp{std::string}, \cpp{std::vector} and others.
\subsubsection*{Arithmetic operators}
\begin{tabular}{l|l}
Operator & Action \\
\hline
\cpp{-} & Subtraction (unary minus) \\
\cpp{+} & Addition (unary plus) \\
\cpp{*} & Multiplication \\
\cpp{/} & Division \\
\cpp{%} & Modulo = Reminder of division, \ie for integers: if \cpp{r = a % b}, then there exists \cpp{c}, such that \cpp{a=b*c + r} \\
\cpp{--} & Decrement (Pre- and Postfix), \ie \cpp{--a} is equivalent to \cpp{a = a - 1}\\
\cpp{++} & Increment (Pre- and Postfix), \ie \cpp{++a} is equivalent to \cpp{a = a + 1} \\
\end{tabular}
\begin{minted}{c++}
int operator++(int& a, int) { // a++
int r = a;
a += 1;
return r;
}
int& operator++(int& a) { // ++a
a += 1
return a;
}
\end{minted}
\subsubsection*{Boolean operators}
Logical operators and comparison operators
\begin{tabular}{l|l}
Operator & Action \\
\hline
\cpp{>} & greater than \\
\cpp{>=} & greater than or equal to \\
\cpp{<} & less than \\
\cpp{<=} & less than or equal to \\
\cpp{==} & equal to \\
\cpp{!=} & unequal to \\
\cpp{&&} & AND \\
\cpp{||} & OR \\
\cpp{!} & NOT \\
\end{tabular}
\begin{rem}
The result of a boolean expression is a \cpp{bool} value, \eg
\cppline{bool out_of_bound = x < min_x || x > max_x}
\end{rem}
\begin{rem}
With \cxx{20}\marginpar{[\cxx{20}]} a new comparison operator is introduced, called \emph{three-way comparison operator} or sometimes also \emph{space-ship operator}. It is written as \cpp{<=>} and returns an object such that
\begin{itemize}
\item \cpp{(a <=> b) < 0} if \cpp{lhs < rhs}
\item \cpp{(a <=> b) > 0} if \cpp{lhs > rhs}
\item \cpp{(a <=> b) == 0} if \cpp{lhs} and \cpp{rhs} are equal/equivalent.
\end{itemize}
and the returned object indicates the type of ordering (strong ordering, partial ordering, weak equality, ...).
\end{rem}
\subsubsection*{Bitwise operators}
Modify or test for the bits of integers
\begin{tabular}{l|l}
Operator & Action \\
\hline
\cpp{&} & AND \\
\cpp{|} & OR \\
\cpp{^} & exclusive OR \\
\cpp{~} & 1-complement \\
\cpp{>>} & right-shift of the bits \\
\cpp{<<} & left-shift of the bits \\
\end{tabular}
\begin{rem}
The logical operators \cpp{<<} and \cpp{>>} are used in C++ often in a different context, namely to \emph{shift} something into a \emph{stream}. Streams are abstractions devices allowing input and output operations. The operator \cpp{<<} is therefore called \emph{insertion operator} and is used with output streams, whereas the operator \cpp{>>} is called \emph{extraction operator} and is used with input streams.
\end{rem}
\begin{example}
While a modern CPU efficiently implements arithmetic and logical operators on integers, one could implement those manually, by using bitwise operations and comparison with 0 only. The following pseudo code implements multiplication of two integers \texttt{a} and \texttt{b} with bit shifts, comparison and addition:
\begin{minted}{pascal}
c := 0
solange b <> 0
falls (b und 1) <> 0
c := c + a
schiebe a um 1 nach links
schiebe b um 1 nach rechts
return c
\end{minted}
It implements kind of a manual multiplication in the binary base but in the uncommon order from right to left.
\footnote{See \url{https://de.wikipedia.org/wiki/Bitweiser_Operator}}
As an exercise, you could implement this algorithm and compare the result with the classical multiplication.
\end{example}
\subsubsection*{Assignment operators}
Compound-assignment operators like \cpp{+=, -=, *=, /=, %= >>=, <<=, &=, ^=, |=} apply an operator to the left and right-side of an assignment, and store the result in the left operand.
Example:
\cppline{a += b // corresponds to a = a + b}
\begin{rem}
Compared to the simple assignment, a compound-assignment does not need to create a temporary and maybe copy it to the left-hand side operand, but works with the operand directly.
\begin{minted}{c++}
struct A { double value; };
A operator+(A const& a, A const& b) {
A c(a); // create local copy of a
c += b;
return c;
}
\end{minted}
but
\begin{minted}{c++}
A& operator+=(A& a, A const& b) {
a.value += b.value;
return a;
}
\end{minted}
\end{rem}
\subsubsection*{Bracket-Access operators}
The round brackets \cpp{()} and the square brackets \cpp{[]} also represent operators, namely \emph{bracket-access operators}. While the square bracket is typically used as vector access and allows only one argument, \eg the vector element index, the round brackets represent a function call and thus allow any number of arguments \texttt{>= 0}.
\subsection*{Sequence of evaluation and side effects}
A sequence point defines any point in a computer program's execution at which it is guaranteed that all side effects of previous evaluations will have been performed, and no side effects from subsequent evaluations have yet been performed.
A side effect is, for example, the change of a variable not directly involved in the computation.
Logical and-then/or-else (\cpp{&&} and \cpp{||}) operators, ternary \cpp{?:} question mark operators, and commas \cpp{,} create sequence points; \cpp{+, -, <<} and so on do not!
With \cxx{17}\marginpar{[\cxx{17}]} several more operations are now sequenced and are safe to include side effects. But in general, you should know that
\begin{guideline}{Attention}
When you use an expression with side effects multiple times in the absence of sequence points, the resulting behavior is \textbf{undefined} in C++. Any result is possible, including one that does not make logical sense.
\end{guideline}
See also: \href{http://en.wikipedia.org/wiki/Sequence_point}{Wikipedia}, \href{http://en.cppreference.com/w/cpp/language/eval_order}{CppReference.com}
For logical operators, at first the left operand is evaluated and based on its value it is decided whether to evaluate the right operand at all or not, \ie
\begin{minted}{c++}
A && B // first evaluate A, if A == true evaluate B and return its value
A || B // first evaluate A, if A == false, evaluate B and return its value
A ? B : C // first evaluate A, if true, evaluate B, otherwise evaluate C
(A,B,C, ...) // first evaluate A, then evaluate B, then evaluate C, ...
f() + g() // it is not specified whether f is evaluated first or g
\end{minted}
\begin{guideline}{Principle}
Never rely on a function call in a logical expression.
\end{guideline}
\begin{rem}
The precedence property is not related to the order of evaluation, but to the rank of the operator. For an arbitrary function \cpp{f(a,b,c,d)} it
is not specified in which order the expressions for a, b, c, d are evaluated.
\end{rem}
\begin{example}
The following expressions have different behavior:
\begin{minted}{c++}
int foo(int a, int b) { return a + b; }
int x = 1;
foo(++x, x++); // Variant 1 (unspecified behavior)
x = 1;
int a = ++x, b = x++;
foo(a, b); // Variant 2 (behavior defined)
\end{minted}
\end{example}
\subsection{Operators as functions}
In C++ nearly all operator can be written (and called) as a regular function. Let \texttt{o} be the symbol of the operator, \eg \texttt{o$~\in$\{+,*,(),+=,<,...\}}, then there zero, one or both of the following implementations are available:
\begin{minted}[frame=none]{c++}
Result operator o(Arg1 a, Arg2 b, ...) // a o b
Result Arg1::operator o(Arg2 b, ...) // Arg1 a; a o b
\end{minted}
The variant 1 implement the operator as a free function, whereas the variant 2 implements the operator as a member function of a class, where \texttt{Arg1} is the name of that class. Whether there is a function representation of the operator and whether it is allowed to \emph{overload} that function is specified in the table below.
\subsection*{Overview}
\begin{tabular}{c|l|l|l|l}
\textbf{\small Precedence} & \textbf{Operator} & \textbf{Description} & \textbf{Associativity} & \textbf{\small Overload} \\
\hline\hline
1 = highest & \cpp{::}& Scope resolution & Left-to-right & ---\\
\hline
2 & \cpp{++} \cpp{--} & Suffix/postfix increment and decrement & Left-to-right & $\checkmark$ $\checkmark$ \\
& \cpp{()} & Function call & & (C)\\
& \cpp{[]} & Subscript & & (C)\\
& \cpp{. ->} & Member access & & --- (C)\\
\hline
3 & \cpp{++ --} & Prefix increment and decrement & Right-to-left & $\checkmark$ $\checkmark$ \\
& \cpp{+ -} & Unary plus and minus & & $\checkmark$ $\checkmark$\\
& \cpp{! ~} & Logical NOT and bitwise NOT & & $\checkmark$ $\checkmark$\\
& \cpp{*} & Indirection (dereference) & & $\checkmark$\\
& \cpp{&} & Address-of & & $\checkmark$\\
\hline
4 & \cpp{.* ->*} & Pointer-to-member & Left-to-right & --- $\checkmark$ \\
\hline
5 & \cpp{* / %} & Multiplication, division, and remainder& & $\checkmark$ $\checkmark$ $\checkmark$ \\
\hline
6 & \cpp{+ -} & Addition and subtraction & & $\checkmark$ $\checkmark$\\
\hline
7 & \cpp{<< >>} & Bitwise left shift and right shift & & $\checkmark$ $\checkmark$\\
\hline
8 & \cpp{<=>} & Three-way comparison operator (\cxx{20}) & & $\checkmark$\\
\hline
9 & \cpp{< <=} & For relational operators $<$ and $\leq$ respectively & & $\checkmark$ $\checkmark$\\
& \cpp{> >=} & For relational operators $>$ and $\geq$ respectively & & $\checkmark$ $\checkmark$\\
\hline
10 & \cpp{== !=} & For relational operators $=$ and $\neq$ respectively & & $\checkmark$ $\checkmark$\\
\hline
11 & \cpp{&} & Bitwise AND & & $\checkmark$\\
\hline
12 & \cpp{^} & Bitwise XOR (exclusive or) & & $\checkmark$\\
\hline
13 & \cpp{|} & Bitwise OR (inclusive or) & & $\checkmark$\\
\hline
14 & \cpp{&&} & Logical AND & & $\checkmark$\\
\hline
15 & \cpp{||} & Logical OR & & $\checkmark$\\
\hline
16 & \cpp{?:} & Ternary conditional & Right-to-left & ---\\
& \cpp{=} & Direct assignment & & (C)\\
& \cpp{#=} & Compound assignment operators [note 1] & & $\checkmark$\\
\hline
17 = lowest & \cpp{,} & Comma & Left-to-right & $\checkmark$
\end{tabular}
[note 1]: \#$~\in\{$\cpp{+, -, *, /, %, <<, >>, &, ^, |}$\}$
In the column \textit{Overload} means (C), the operator can only be implemented as member function of a class, whereas $\checkmark$ allows to write the operator as member function or free function.
A more complete table can also be found at \url{http://en.wikipedia.org/w/index.php?title=C++\_operators}, or \url{https://en.cppreference.com/w/cpp/language/operator_precedence}.
This diff is collapsed.
......@@ -77,8 +77,8 @@ There are exercises every week to practice the C++ programming. During the semes
\input{01_introduction}
\input{02_basics}
%\input{03_operators}
%\input{04_functions}
\input{03_operators}
\input{04_functions}
%\input{05_references}
%\input{06_arrays}
%\input{07_namespaces}
......
---
class: center, middle
# Arithmetic Operators
# Arithmetic Operators and Assignment Operators
---
# Arithmetic and Assignment Operators
## Arithmetic
For integer and floating point types:
```c++
x + y;
x - y;
x * y;
x / y;
```
For integer types, the **modulus** operator:
```c++
x % y;
```
> .h3[Remark:] No operator for power, like `^` in Matlab or `**` in Python!
---
# Arithmetic and Assignment Operators
## Assignment
Standard assignment (as with initial values)
```c++
x = y;
```
Assignment can be combined with arithmetic, so
```c++
x = x + y; x = x - y;
x = x * y; x = x / y;
x = x % y; // for integers
```
is the same as
```c++
x += y; x -= y;
x *= y; x /= y;
x %= y; // for integers
```
These are called **compound assignment** operators.
---
# Arithmetic and Assignment Operators
## Increment and Decrement
In C++ (like in C) exist special versions for
variable increment/decrement:
```c++
int n = 0;
++n; // same as n = n + 1 or n += 1
n++;
--n; // same as n = n - 1 or n -= 1
n--;
```
Difference between **preincrement** and **postincrement**,
e.g.
```c++
int n = 5, m = 5 * n++;
```
results in `n = 6` and `m = 25`, whereas
```c++
int n = 5, m = 5 * ++n;
```
results in `n = 6` and `m = 30`.
---
# Arithmetic and Assignment Operators
## Examples
```c++
int n1 = 3, n2 = 4;
int n3 = 0;
n3 = 2 * n1 - n2 + n1 / 2;
n2 *= 6;
n1 -= 8;
double const approx_pi = 355.0 / 113.0;
double f1 = approx_pi / 2.0;
double f2 = approx_pi * approx_pi + 10.0 * f1;
f1 /= 5.0;
```
> .h3[Attention:] The division `355/113` for integers is different than for floats `355.0/113.0`
> .h3[Remark:] If you mix integer and float the operands are (implicitly) converted (cast) to the floating
> point type first.
---
# Arithmetic and Assignment Operators
## Division by Zero and other undefined Operations
### With floating point types:
- For \(x \ne 0.0\): \(x / 0.0 =\) `Inf`, with `Inf` is a special floating point number for infinity.
- For \(x = 0.0\): \(x / 0.0 =\) `NaN` (not-a-number) is another special floating point number for
*invalid* or *not defined* results, e.g., square root of negative numbers.
Both operations are (usually) performed without notification, i.e., the
program continues execution with these numbers. NaNs often occur with
uninitialized variables, therefore RAII!
> .h3[Remark:] Check with `std::isnan` and `std::isinf` whether a result is NaN or Inf.
---
# Arithmetic and Assignment Operators
## Division by Zero and other undefined Operations
### With floating point types:
- For \(x \ne 0.0\): \(x / 0.0 =\) `Inf`, with `Inf` is a special floating point number for infinity.
- For \(x = 0.0\): \(x / 0.0 =\) `NaN` (not-a-number) is another special floating point number for
*invalid* or *not defined* results, e.g., square root of negative numbers.
Both operations are (usually) performed without notification, i.e., the
program continues execution with these numbers. NaNs often occur with
uninitialized variables, therefore RAII!
### In integer arithmetic:
\(x / 0\) leads to **undefined behavior**, i.e., the
program (usually) aborts.
---
# Relational and Logical Operators
## Comparison
Standard comparison for integer and floating point types:
```c++
x > y; // bigger than
x < y; // less than
x >= y; // bigger or equal
x <= y; // less or equal
x == y; // equal
x != y; // unequal
```
Logic Logical operators `and`, `or` and `not`
for boolean values:
```c++
b1 && b2; // and
b1 || b2; // or
! b1; // not
```
---
# Relational and Logical Operators
## Sequenced evaluation
Logical expressions are only evaluated until the
result is known. This is important if the expression contains function
calls (see later), or a sub expression is only allowed if a previous sub
expression is `true`.
```c++
int x = 2;
int y = 4;
int z = 4;
// z == 4 is not tested
bool b = (x == 2 && y == 3 && z == 4);
// only x == 2 is tested
b = (x == 2 || y == 3 || z == 4);
// correct, since x != 0 in "y/x"
b = (x != 0 && y / x > 1);
```
> .h3[Principle:] Never rely on a function call in logical expressions!
---
# Relational and Logical Operators
## Floating Point Comparison
> .h3[Coding Principle:] For floating point types, avoid equality checks due to
> inexact arithmetic.
Better is interval test:
```c++
double f1 = std::sqrt(2.0);
double f2 = f1 * f1;
bool b = (f2 == 2.0); // unsafe
double const eps = 1e-14;
b = f2 > 2.0 - eps && f2 < 2.0 + eps; // safe
b = std::abs(f2 - 2.0) < eps; // better
```
--
> .h3[Note:] Floating point numbers are not equally distributed
---
# Relational and Logical Operators
## Floating Point Comparison
- Accuracy of numerical algorithms often measured in "ULPs" -
[units in the last place](https://en.wikipedia.org/wiki/Unit_in_the_last_place)
- Comparison up to "some" ULPs
- `std::numeric_limits` provides *eps*
```c++
double const eps = std::numeric_limits<double>::epsilon();
double const min = std::numeric_limits<double>::min();
int const ulp = 2;
bool b = std::abs(x-y) <= eps * std::abs(x+y) * ulp || std::abs(x-y) < min;
```
> .h3[Remark:] Mathematical functions often have an accuracy of a few ULPs, see
> [Errors-in-Math-Functions](https://www.gnu.org/software/libc/manual/html_node/Errors-in-Math-Functions.html)
---
# Precedence and Associativity of Operators
## Precedence
When evaluating complex expressions, what is evaluated first,
and in which order? Example:
```c++
int n1 = 2 + 3 * 4 % 2 - 5;
int n2 = 4;
bool b = n1 >= 4 && n2 != 3 || n1 < n2;
```
Precedence of arithmetics follows algebraic/logical precedence, e.g.,
`*` before `+`, `&&` before `||`. Increment (`++`) and decrement (`--`) have higher, assignment
(`=`, `+=`, ...) has lower priority.
*Parentheses* have highest priority.
```c++
int n1 = (2 + ((3 * 4) % 2) - 5);
int n2 = 4;
bool b = (((n1 >= 4) && (n2 != 3)) || (n1 < n2));
```
---