Key Takeways

Video Addendum

Boolean operators

Just like you are able to operate on ints with multiplication, addition, subtraction, division, and modulo, you can also operate on booleans. These are called boolean operators. The boolean operators are:

  • not !
  • and &&
  • or ||
  • xor ^

For each of the operators, you can both read the summary of how it works and see what it’s result will be by using the truth tables below.

not A or !A is true if A is false, and vice versa.

A !A
true false
false true

A and B or A && B is true whenever both A and B are true, otherwise its false.

A   B   A && B
true && true = true
true && false = false
false && true = false
false && false = false

A or B or A || B is true whenever any of A or B are true, otherwise its false.

A   B   A || B
true || true = true
true || false = true
false || true = true
false || false = false

A xor B or A ^ B is true whenever only one of A or B are true, otherwise its false. xor is short for exclusive-or.

A   B   A ^ B
true ^ true = false
true ^ false = true
false ^ true = true
false ^ false = false

Use cases

Often you’ll be using boolean operators to express what you want your code to do. For example you may have the following problem assigned to you.

Ask the user for a number. 
If it divides evenly by both 3 and 5, print "DONG!". 
Otherwise, if the number divides evenly by 3, print "Tick". 
Otherwise, if the number divides evenly by 5, print "Tock". 
In all other cases print out the number.
int main() {
    // Asking the user for a number.
    int number = GetUserInput();

    // Using variables to get the divisbility of the number.
    bool divides_by_3 = (number % 3 == 0); // True if number evenly divides 3.
    bool divides_by_5 = (number % 5 == 0); // True if number evenly divides 5.

    // If the number divides by 3 AND 5.
    if (divides_by_3 && divides_by_5) {
        std::cout << "DONG!";
    }

    // If the number divides only by 3 (but doesn't divide by 5).
    if (divides_by_3 && !divides_by_5) {
        std::cout << "Tick";
    }

    // If the number divides only by 5 (but doesn't divide by 3).
    if (divides_by_5 && !divides_by_3) {
        std::cout << "Tock";
    }

    // If a number doesn't divide by 3 and 5.
    if (!divides_by_3 && !divides_by_5) {
        std::cout << number;
    }

    return 0;
}

This is how you read each of the if clauses.

    // If divides_by_3 is true AND divides_by_5 is true, then execute the block.
    // This will trigger only when both divides_by_3 and divides_by_5 are true.
    if (divides_by_3 && divides_by_5)
    // If divides_by_3 is true AND NOT (divides_by_5 is true), then execute the block.
    // This will trigger only when divides_by_3 is true and divides_by_5 is false.
    if (divides_by_3 && !divides_by_5)
    // If divides_by_5 is true AND NOT (divides_by_3 is true), then execute the block.
    // This will trigger only when divides_by_3 is false and divides_by_5 is true.
    if (divides_by_5 && !divides_by_3)
    // If NOT (divides_by_3 is true) AND NOT (divides_by_5 is true), then execute the block.
    // This will trigger only when both divides_by_3 and divides_by_5 are false.
    if (!divides_by_3 && !divides_by_5))

De Morgan’s Law

One important concept to grasp regarding boolean operators is that you can combine values in different ways and still get the same result. De Morgan’s Law specifically states:

  1. !(a && b) is the same as (!a || !b).
  2. !(a || b) is the same as (!a && !b). Notice that De Morgan’s Law gives us a way to swap ORs || with ANDs && and vice versa.

Building Truth Tables

bool var_a = /*either true or false*/;
bool var_b = /*either true or false*/;

// option_0 = NOT (var_a OR var_b)
bool option_0 = !(var_a || var_b);
// option_1 = (NOT var_a) AND (NOT var_b)
bool option_1 = ((!var_a) && (!var_b));

Let’s start by building a truth table. We have 2 inputs - var_a and var_b - and 2 outputs - option_0 and option_1.

var_a var_b option_0
!(var_a || var_b)
option_1
((!var_a) && (!var_b))
       

We know var_a can be either true or false so lets fill that in.

var_a var_b option_0
!(var_a || var_b)
option_1
((!var_a) && (!var_b))
true      
false      

We also know var_b can be either true or false, however this is the case for all possibilities of var_a. This is shown using this table.

var_a var_b option_0
!(var_a || var_b)
option_1
((!var_a) && (!var_b))
true true    
true false    
false true    
false false    

Now we just fill in the values for our outputs options_0 at first.

var_a var_b option_0
!(var_a || var_b)
option_1
((!var_a) && (!var_b))
true true !(true || true)  
true false !(true || false)  
false true !(false || true)  
false false !(false || false)  

Simplifing inside the ( ) we get:

var_a var_b option_0
!(var_a || var_b)
option_1
((!var_a) && (!var_b))
true true !(true)  
true false !(true)  
false true !(true)  
false false !(false)  

Simplifying again we get:

var_a var_b option_0
!(var_a || var_b)
option_1
((!var_a) && (!var_b))
true true false  
true false false  
false true false  
false false true  

If you follow a similar process for option_1, you will get the final table:

var_a var_b option_0
!(var_a || var_b)
option_1
((!var_a) && (!var_b))
true true false false
true false false false
false true false false
false false true true

How are they the same? De Morgan’s Law!

Assignment

  1. Write truth tables for the following expressions assuming var_a, var_b, and var_c are boolean inputs.
    • var_c || !var_c
    • var_a && !var_a
    • !var_a ^ (var_a || var_b) (Remember ^ is XOR).
    • var_a && (var_a || var_b)
    • (var_b && var_a) || (var_c && !var_b)
    • var_c || (!var_c && var_a) || !(!var_c && !var_b)
  2. Optional: What are simpler, equivalent expresions for each of the ones above that would always produce the same truth table?
  3. What will Code Sample 0 output to the console for the user inputs below? Figure out the answer without running the code. Then run the code in a Repl to double check your answer. Remember to estimate all new lines as well whenever stating what is printed out.
    • x = 5, y = 12
    • x = 1000, y = -2
    • x = 11, y = 23
    • x = -8, y = 2
  4. Write an expresion that produces an equivalent Truth Table to A ^ B without using ^.
    • HintTry using && ! and ||
  5. Use De Morgan’s Law to write equivalent expressions without using &&.
    • A && (!B && !C)
    • B && (!A && C) && (!A && !B)

Code Samples

Sample 0
int main() {
    int x = GetUserInput();
    int y = GetUserInput();
    if (x < 10) {
        std::cout << "Small ";
    }
    if (x < 10 && !(y % 11 == 0)) {
        std::cout << "Medium " << std::endl;
    }
    if (x > 20 || (y < x) ^ !(x % 3 != 2)) {
        std::cout << "Large ";
    }

    if (y < 10) {
        std::cout << "Giant ";
    }

    std::cout << "Case" << std::endl;
}


End of Assignment Checklist

  • I finished all the assignments.
  • I shared my assignments with others.
  • I provided feedback for assignments of at least 2 others.
  • I addressed the feedback from others and thanked them for the review.