Lab 01 Examples¶

Click <shift> <enter> in each code cell to run the code. Be sure to start with the #include directives to load the required libraries.

In [1]:
#include <iostream>

// These directives just suppress compiler warnings and can be omitted.
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wconstant-logical-operand"

using namespace std;

Integer Equivalents of Boolean Values¶

false = 0
true = 1 (or any non-zero number)

In [2]:
bool var_1 = false;
bool var_2 = true;
bool var_3 = 0;
bool var_4 = 1;
bool var_5 = 42;  // non-zero numbers are considered truem

cout << "Boolean values:" << endl;
cout << "var_1 (false) = " << var_1 << endl;
cout << "var_2 (true) = " << var_2 << endl;
cout << "var_3 (0) = " << var_3 << endl;
cout << "var_4 (1) = " << var_4 << endl;
cout << "var_5 (42) = " << var_5 << endl << endl;
Boolean values:
var_1 (false) = 0
var_2 (true) = 1
var_3 (0) = 0
var_4 (1) = 1
var_5 (42) = 1

The Difference Between Bitwise & and Logical && AND Operators¶

The bitwise AND operator & performs the AND operation on each corresponding bit of two integers.
The logical AND operator && evaluates two boolean expressions and returns a boolean true or false.

In [3]:
cout << "(false & true) = " << (false & true) << endl;
cout << "(true & true) = " << (true & true) << endl;
cout << "(false & false) = " << (false & false) << endl;
cout << "(false && true) = " << (false && true) << endl;
cout << "(true && true) = " << (true && true) << endl;
cout << "(false && false) = " << (false && false) << endl << endl;

cout << "(0 & 1) = " << (0 & 1) << endl;
cout << "(1 & 1) = " << (1 & 1) << endl;
cout << "(0 & 0) = " << (0 & 0) << endl;
cout << "(0 && 1) = " << (0 && 1) << endl;
cout << "(1 && 1) = " << (1 && 1) << endl;
cout << "(0 && 0) = " << (0 && 0) << endl << endl;

cout << "Non-zero integers are considered true." << endl;
cout << "(2 && 3) = " << (2 && 3) << endl << endl;
(false & true) = 0
(true & true) = 1
(false & false) = 0
(false && true) = 0
(true && true) = 1
(false && false) = 0

(0 & 1) = 0
(1 & 1) = 1
(0 & 0) = 0
(0 && 1) = 0
(1 && 1) = 1
(0 && 0) = 0

Non-zero integers are considered true.
(2 && 3) = 1

Binary Representation:

00 zero
01 one
10 two
11 three

Bitwise 2 AND 3 in binary is 10 & 11 = 10

  10
& 11
----
  10
In [4]:
cout << "Bitwise 2 AND 3 in binary is 10 & 11 = 10" << endl;
cout << "(2 & 3) = " << (2 & 3) << endl << endl;
Bitwise 2 AND 3 in binary is 10 & 11 = 10
(2 & 3) = 2

Short Circuit Evaluation with Logical AND &&¶

In [5]:
cout << "Short-circuit evaluation with logical AND (&&):" << endl;
for (int divisor = -1; divisor <= 1; ++divisor) {
    cout << "x = " << divisor << " : (x != 0 && (10 / " << divisor << ") > 1) = " 
        << (divisor != 0 && (10 / divisor) > 1) << endl;
}
cout << endl;
Short-circuit evaluation with logical AND (&&):
x = -1 : (x != 0 && (10 / -1) > 1) = 0
x = 0 : (x != 0 && (10 / 0) > 1) = 0
x = 1 : (x != 0 && (10 / 1) > 1) = 1

Without short-circuit evaluation, a division by zero error would occur when the divisor is 0.
With short-circuit evaluation, the second condition isn't evaluated if the first condition is false.
false is returned immediately if the first conditions is false, because both conditions must be true for the whole expression to be true.

The Difference Between Bitwise | and Logical || AND Operators¶

The bitwise OR operator | performs the OR operation on each corresponding bit of two integers.
The logical OR operator || evaluates two boolean expressions and returns a boolean true or false.

In [6]:
cout << "(false | true) = " << (false | true) << endl;
cout << "(true | true) = " << (true | true) << endl;
cout << "(false | false) = " << (false | false) << endl;
cout << "(false || true) = " << (false || true) << endl;
cout << "(true || true) = " << (true || true) << endl;
cout << "(false || false) = " << (false || false) << endl << endl;

cout << "(0 | 1) = " << (0 | 1) << endl;
cout << "(1 | 1) = " << (1 | 1) << endl;
cout << "(0 | 0) = " << (0 | 0) << endl;
cout << "(0 || 1) = " << (0 || 1) << endl;
cout << "(1 || 1) = " << (1 || 1) << endl;
cout << "(0 || 0) = " << (0 || 0) << endl << endl;

cout << "Non-zero integers are considered true." << endl;
cout << "(2 || 3) = " << (2 || 3) << endl << endl;
(false | true) = 1
(true | true) = 1
(false | false) = 0
(false || true) = 1
(true || true) = 1
(false || false) = 0

(0 | 1) = 1
(1 | 1) = 1
(0 | 0) = 0
(0 || 1) = 1
(1 || 1) = 1
(0 || 0) = 0

Non-zero integers are considered true.
(2 || 3) = 1

Binary Representation:

00 zero
01 one
10 two
11 three

Bitwise 2 OR 3 in binary is 10 | 11 = 10

  10
| 11
----
  11
In [7]:
cout << "Bitwise 2 OR 3 in binary is 10 | 11 = 11" << endl;
cout << "(2 | 3) = " << (2 | 3) << endl << endl;
Bitwise 2 OR 3 in binary is 10 | 11 = 11
(2 | 3) = 3

Short Circuit Evaluation with Logical OR ||¶

In [8]:
cout << "Short-circuit evaluation with logical OR (||):" << endl;
for (int divisor = -1; divisor <= 1; ++divisor) {
    cout << "x = " << divisor << " : (x == 0 || (10 / " << divisor << ") > 1) = " 
        << (divisor == 0 || (10 / divisor) > 1) << endl;
}
cout << endl;
Short-circuit evaluation with logical OR (||):
x = -1 : (x == 0 || (10 / -1) > 1) = 0
x = 0 : (x == 0 || (10 / 0) > 1) = 1
x = 1 : (x == 0 || (10 / 1) > 1) = 1

Without short-circuit evaluation, a division by zero error would occur when the divisor is 0.
With short-circuit evaluation, the second condition isn't evaluated if the first condition is true.
true is returned immediately if the first conditions is true, because one true condition is sufficient to render the expression true.

Using the NOT operator ! to Flip Boolean Values¶

In [9]:
bool my_bools[5] =   {0, 1, 0, 1, 1};
bool your_bools[5] = {1, 1, 1, 1, 0};

cout << "Demonstrate the use of the NOT operator (!):" << endl;

for (int b = 0; b < 5; b++) {
    cout << "my_bools[" << b << "] = " << my_bools[b] 
         << ", !my_bools[" << b << "] = " << !my_bools[b] << endl;
}
cout << endl;

for (int b = 0; b < 5; b++) {
    cout << "your_bools[" << b << "] = " << your_bools[b] 
         << ", !your_bools[" << b << "] = " << !your_bools[b] << endl;
}
cout << endl;
Demonstrate the use of the NOT operator (!):
my_bools[0] = 0, !my_bools[0] = 1
my_bools[1] = 1, !my_bools[1] = 0
my_bools[2] = 0, !my_bools[2] = 1
my_bools[3] = 1, !my_bools[3] = 0
my_bools[4] = 1, !my_bools[4] = 0

your_bools[0] = 1, !your_bools[0] = 0
your_bools[1] = 1, !your_bools[1] = 0
your_bools[2] = 1, !your_bools[2] = 0
your_bools[3] = 1, !your_bools[3] = 0
your_bools[4] = 0, !your_bools[4] = 1

A Closing Thought¶

Consider the AND operator. Consider the OR operator.
Given the topic of set theory, which operator is more useful for computing an intersection? Which operator is more useful for computing a union?

Before beginning to write your program, think about the design.¶

  • What operations does your program need to perform?
    • Can these operations be separated into functions?
    • If so, what parameters will these functions receive? What values (if any) will they return?
    • Might it be useful to have any utility functions such as a print function?
  • What data types will you use to store the data?
    • Will you use indexable data structures like arrays or vectors?
    • Of what data type will those arrays or vectors be?
    • How will you represent your data?
      • Will the data be sorted? Does it need to be?
      • What types of calculations will be performed on the data? Do you need to perform any basic arithmetic on the data like addition, subtraction, multiplication or division?
      • If you have multiple arrays or vectors, what size will they be? Will they all be the same size? Would you want them to be? What would be the advantages and disadvantages if they were?

Have fun designing before you have fun programming!