- what are
*logical operations*? - what is the precendence of C++ operations?
- what are
*type conversions*?

A *logical expression* evalutes to a Boolean value: `true`

or `false`

.
We use logical expressions in *conditions* for flow control (e.g.,
`if`

statements and `while`

loops).
So far, our logical expressions have consisted of *comparison* operators:

Operator | Operation |
---|---|

`<` |
Less than? |

`>` |
Greater than? |

`<=` |
Less than or equal to? |

`>=` |
Greater than or equal to? |

`==` |
Equal to? |

`!=` |
Not equal to? |

That’s all we’ve needed thus far in the course, but now we will start to write
more complicated logical expressions.
These will involve *logical operations*.
Logical operations, just like *arithmetic* and *comparison* operations,
operate on values and **evaluate to a result**.
Some operate on two values (just like `x + y`

): these are called
**binary** operations.
Others operate on a single value (just like `-x`

): these are called
**unary** operations.
Logical operatons, like comparison operations, always evaluate to
`true`

or `false`

.
Unlike arithemetic or comparison operations, however,
**logical operations also operate on Boolean values**.

We will concern ourselves with four logical operations in this course:

Keyword | Operator | Kind | Evaluates to true iff: |
---|---|---|---|

`and` |
`&&` |
Binary | both operands are true |

`or` |
`||` |
Binary | at least one operand is true |

`xor` |
`^` |
Binary | exactly one operand is true |

`not` |
`!` |
Unary | the operand is false |

These operations mostly correspond that what you’d expect from colloquial use
(in everyday speech).
However, we can define them a bit more rigorously using a *truth table*.
As an exercise, **fill in the following truth table**.
Use the definitions of the various logical operators above.

`a` |
`b` |
`a and b` |
`a or b` |
`a xor b` |
`not a` |
---|---|---|---|---|---|

F | F | ||||

F | T | ||||

T | F | ||||

T | T |

These operations will allow us to construct more interesting conditions like
“$n$ is between 3 and 7”.
Mathematically, we would write that expression as $3 \leq n \leq 7$,
but `3 <= n <= 7`

**does not have the same meaning in C++**.
Let’s explore why below.

We have previously used an informal notion of precedence when evaluating expressions: “multiplication and division occur before addition and subtraction”. Now, when we add the logical operations into the mix of the kinds of things we can put in our expressions, things get a little bit more complicated. Here is a table that shows the precedence of all of the operations we now know about:

Operator | Description |
---|---|

`()` |
sub-expression |

`!` , `+` , `-` |
logical not, unary positive, unary negative |

`*` , `/` , `%` |
multiplication, division, modulus |

`+` , `-` |
addition, subtraction |

`<` , `<=` , `>` , `>=` |
relational inequalities |

`==` , `!=` |
equal / not equal |

`and` |
logical and |

`or` |
logical or |

`=` |
assignment |

It is very common, in a variety of algorithms, to need to update a variable
in-place by applying an arithmetic operation.
For example, our
`printNumbersUpTo`

example
included the statement `i = i + 1`

, and our
`factorial`

example included
`number = number - 1`

.
In C++ (and many other languages!), we can write these sorts of
“apply an arithmetic operation and then save the result in the same variable”
using *compound operations*.
Here are a table of such operations:

Operation | Equivalent to |
---|---|

`x += y` |
`x = x + y` |

`x -= y` |
`x = x - y` |

`x *= y` |
`x = x * y` |

`x /= y` |
`x = x / y` |

So, instead of writing `x = x * 2`

, we can write `x *= 2`

.
Instead of `i = i + 1`

, we can write `i += 1`

.
However, in fact, the need to *increment* (add one) and *decrement* (subtract
one) is so common that they have **their own operators**.
The `++`

operator means, “add one to a variable and store the incremented value
back in the variable” and `--`

means the same for subtraction.

Operation | Equivalent to | Also equivalent to |
---|---|---|

`i++` |
`i += 1` |
`i = i + 1` |

`i--` |
`i -= 1` |
`i = i - 1` |

The `++`

and `--`

operators can be applied either **before** or **after**
a variable (e.g., `i++`

or `++i`

).
In both cases, the value will be incremented by one.
The only difference between them is what the whole expression will evaluate to:
the *old* value of the variable or the *new* value.
This distinction will not matter in code I show you in ENGI 1020.
In fact, code that relies on the distinction between `i++`

and `++i`

may be
**a bit too clever for its own good**: this kind of tricky code is also
tricky to understand and tricky to debug.

What does the following code output?

```
int n = 4.6 * 2;
double x = 7 / 2;
cout << "n: " << n << ", x: " << x << endl;
```

In the first case, we are multiplying a floating-point number by an integer,
then storing the result in an integer variable.
**The computer cannot do this directly.**
In the second case, we are dividing an integer by an integer and then storing
the result in a floating-point variable.
**The result of this initialization might surprise you.**

When we perform an operation on integer and floating-point numbers, we must
*convert* one to the other.
In C++ (and many, but **not all** programming languages), the compiler will
automatically convert an integer to a floating-point number when it’s involved
in a floating-point operation (addition, subtraction, etc.).
This *numeric promotion* is **safe** in the sense that
**no information is lost**: it’s safe to refer to `3`

as `3.0`

, etc.
The same kind of promotion occurs when we store integer values in
floating-point variables (including parameters!).

In the other direction, we can also assign floating-point values to integer
variable (including parameters).
When this happens in many — but not all — programming languages,
the floating-point value is *truncated*: anything after the decimal place
is simply chopped off.
Even though `4.9`

is almost `5`

, it will be truncated to `4`

if stored in an
integer variable.

In most programming languages, numbers can be converted to Boolean values and vice-versa. Boolean values are converted to integer types as follows:

`true`

becomes 1 and`false`

becomes 0.

Integer types include `int`

, `long int`

and even `char`

(which, after all, is
an integer *code* for a character).
The above conversion might be about what you expect, but you may find the
reverse to be slightly surprising:

- 0 becomes
`false`

and - anything else becomes
`true`

.

These conversions are often applied automatically. For example, the following code will compile and run just fine:

```
int i = getNumberFromUser();
if (i)
{
cout << "i is not zero!\n";
}
```

When evaluating a boolean condition, we follow the order of operations to reduce
the condition down to a single `true`

or `false`

value.
However, sometimes we don’t need to evaluate the whole condition to know the
answer!
Consider the following code:

```
bool sleptWell = false;
bool haveCoffee = true;
if (haveCoffee or sleptWell)
{
giveLecture();
}
```

This condition will be `true`

if **either haveCoffee or sleptWell are
true**.
Consequently, as soon as we see that

`haveCoffee`

is true, there is no need to
continue checking the rest of the condition (`sleptWell`

): we already know what
the answer is going to be.
This is the ```
bool foo(double x) { return (x > 0); }
bool bar(double x) { cout << x; return (x > 1); }
int main()
{
if (foo(2) or bar(2))
{
cout << "wibble";
}
return 0;
}
```

In this case, the behaviour of the program is changed by the short-circuit
property: the `bar`

function will never run.
This is worth understanding when we write conditions for `if`

statements
and loops!

Given four integer variables, A, B, C and D,
write four C++ functions functions to return `true`

iff:

- any of them is negative,
- A is the smallest value,
- any pair is equal and
- the product of any pair is equal to the product of the other pair.

By default, the C++ compiler will *truncate* floating-point numbers when storing
them in integers, i.e., chop off anything after the decimal point.
The standard library does include several
rounding functions,
but let’s write one for practice.
**Write a function that rounds a floating-point number to the nearest integer.**
It would be advisable to **design before implementing**: create the contract of
the function and think about all of its logic, the special cases it needs to
handle, how to test it, etc., **before you write any code**.

(c) 2009â€“2016 Michael Bruce-Lockhart, Theo Norvell, Dennis Peters and Jonathan Anderson. Licensed under a Creative Commons Attributionâ€“Noncommercialâ€“Share-Alike 2.5 Canada License. Permissions beyond the scope of this license may be available at theteachingmachine.org.