Contents

Logic

At the moment, we’ve only looked at computer programs that perform the same instructions every time they’re run. In this chapter we’ll look at how to create computer programs that do different things depending on the circumstances.

Programmatic thinking

Fundamentally, a computer is nothing more than a machine. A complex machine that can do all sorts of things - but still nothing less than a dumb machine.

I say a ‘dumb’ machine because computers, clever as they seem, aren’t able to reason for themselves. Computers are only ever capable of doing exactly what they’re told - and nothing else. Computers are like actors in a play that can only do what the script tells them.

This is a blessing and a curse. In one sense it’s great because we can tell a computer to perform a complicated and repetitive task and it will get it right 100% of the time. However problems arise when we tell the computer to do something that seems correct at first glance, but is actually subtly wrong. Let’s look at an example of how that might happen.

Teaching a robot life skills

Imagine you had to teach someone how to make a cup of tea. You might tell them:

Put some water in the kettle. When it’s boiled put a teabag in the cup. Then pour the water in. Wait a bit then take out the teabag.

Now any sane person would be able to follow these instructions. However imagine you’re teaching a robot this most basic of life skills. If you gave a robot these instructions, it probably wouldn’t understand what to do. Why so? Well let’s look at the first instruction again:

Put some water in the kettle

The robot might ask:

‘Where do I get the water?’ ‘How do I open the kettle?’

Sighing, you offer more specific instructions:

Open the kettle by the lid. Move the kettle under the tap and turn the tap on. Close the lid and then put the kettle back on it’s base. When it’s boiled…. and so on.

The robot then bursts into life. It opens the kettle lid, then moves the kettle under the tap. It turns the tap on full blast then immediately closes the lid splashing water everywhere. It then puts the soaking wet kettle back on it’s base then falls over because it doesn’t understand the next instruction.

What a nightmare! What went wrong?

Well, first of all the robot didn’t understand that it had to wait at least a couple of seconds in order for the kettle to fill up. Next you didn’t say to turn the tap off, so when the robot closed the lid the water went everywhere. Also the kettle is now soaked, so it might even be dangerous to turn the power on and start boiling the water. Good job the robot fell over because it couldn’t understand the next instruction!

Ok, third time’s the charm, you think. Robot! Here are you new instructions:

Open the kettle by the lid. Move the kettle under the tap and turn the tap halfway. Wait 10 seconds. Turn the tap off. Close the lid and then put the kettle back on it’s base. When it’s boiled….

Again the robot bursts into life and grabs the kettle. It fills it up with water, correctly turning the tap on and off. It puts the kettle back on its base and then stares at the kettle, motionless. After a few seconds you begin to wonder what’s wrong. After a minute you get frustrated and hit the reset button on the back of the robot’s head. The robot droops down, then bursts back into life and repeats the process, this time filling the kettle to overflow so it gets soaking wet, again. It then places the kettle back on its base and stares dumbly at it.

What’s wrong this time? Well although we were specific enough for the first few steps, it turns out we never told the robot that in order to boil the water you have to turn the kettle on! This means we entered an error state where the robot was waiting for a condition that would never happen - the kettle boiling. Furthermore, when we reset the robot we never told it how to proceed if the kettle was already full, which meant it just did a stupid thing and filled the kettle with water again until it overflowed.

Hopefully you get the idea here. When we’re writing computer programs we have to be extremely specific about what we want to happen. We can’t just assume the computer will do a reasonable thing because that’s what we thought ought to happen when we told it what to do.

Logic

In order to write a program that allows a robot to make a cup of tea, we need to employ a set of rules known as ‘logic’.

Now we often use the word ‘logic’ informally to mean a structured or rational way of thinking. However when it comes to computer programming, logic refers to a mathematical framework that allows us to determine the truth of a given statement.

Consider the following statement:

The kettle is empty

This is an assertion - it represents something that can only ever be true or false. If the kettle is empty, then The kettle is empty is true. If the kettle is not empty, then The kettle is empty must be false. So far, so simple.

By considering the truth or falsehood of this statement, we can tell our computer program to do something different. We can do this using the ‘If’ construct.

So a program written in a made up programming language might look something like this:

If The kettle is empty Then
    Fill up the kettle
Else
    Turn the kettle on
End If

This construct follows the if...Then...Else pattern, which is common in many programming languages. If the condition is true, then do something. Otherwise do something else.

So, if the assertion The Kettle is empty is true, then fill up the kettle. Otherwise turn the kettle on.

Logical operators

For arguments sake, let’s say that in your computer program you have access to two assertions about the state of the kettle, which can be either true or false:

  • The kettle is empty
  • The kettle lid is open

Given this information, how can you write a program that can figure out if you should fill up the kettle?

Well, we need to think of a rule to follow about filling up the kettle. If the rule is broken, then we can’t fill up the kettle.

The rule could be: only fill up the kettle with water if the kettle is empty or the kettle lid is open.

Now that we’ve formulated a rule, we need to figure out how to represent it in our program. An If statement is the obvious choice. The rule involves two assertions - ‘the kettle is empty’ and ‘the kettle lid is open’, so we need a way of combining these assertions in a meaningful way to match our rule.

Luckily, the mathematicians thought about that already! It’s possible to combine assertions using mathematical rules known as ‘operators’. These let you create a composite assertion, called an ‘expression’. There are many such operators, and among the most commonly used operators are AND and OR.

The OR operator seems like the correct thing to use. OR evaluates to true if one of the assertions on the left or the right are true. An If statement in our made-up programming language might look like this:

If The kettle is empty OR The kettle lid is open Then
    Fill up the kettle
Else
    Turn the kettle on
End If

Truth tables

To make sure we’ve got things correct, we can use something called a ‘truth table’ to figure out if our rule is going to give us the right result. Truth tables show all the possible combinations of assertions, and what the result will be.

Our rule looks like this:

only fill up the kettle with water if the kettle is empty, or the kettle lid is open.

And the expression that we used in our If statement to match that rule looks like this:

The kettle is empty OR The kettle lid is open

The truth table for our expression therefore looks like this:

The kettle is empty The kettle lid is open The kettle is empty OR The kettle lid is open
True False True
True True True
False True True
False False False

Ah, it looks like there is something seriously wrong with our logic! Look at the first entry again:

The kettle is empty The kettle lid is open The kettle is empty OR The kettle lid is open
True False True

Looks like this expression will allow us to fill up the kettle if ‘the kettle lid is open’ is false - which means the kettle lid is closed.

Truth tables allow us to see errors in our logic that we might not otherwise catch. Because there is only a finite number of states that the assertions can be in, we can be 100% sure when something is working - or not working in our case!

Looks like we need to use a different logical operator. As I mentioned before, the AND operator will do the trick. Let’s look at the truth table for AND:

The kettle is empty The kettle lid is open The kettle is empty AND The kettle lid is open
True False False
True True True
False True False
False False False

That looks better. The previous case that we knew is wrong now evaluates to ‘False’. We can see at a glance that we only ever fill up the kettle when it’s sane to do so.

Illogical!

Logic can be less-than-obvious at times. Say that the kettle truly is full, what should the following statement evaluate to:

The Kettle is empty is equal to False

True or False?

True!

This is because the kettle is full, therefore The Kettle is empty is actually False. We can then substitute the value of The kettle is empty with False. This would leave us with:

False is equal to False

False is equal to False, which means the above assertion is actually True.

Negative!

That was a simple example - let’s make things more complicated. Another common aspect of logic in computer programming is ‘negation’, denoted by the word NOT. Negation reverses the value of an assertion.

So if the kettle truly is full, what would the following evaluate to?

NOT the kettle is empty

True again. We know that the kettle is empty is False. Therefore, negating it with NOT means it becomes the opposite of False - True.

Say that the kettle is full and the lid is open. What does this evaluate to?

NOT(the kettle is empty AND the lid is open)

(I’ve used brackets to indicate everything inside is to be negated).

Let’s evaluate it using substitution:

We know the kettle is full - so the kettle is empty is False. Using substitution the kettle is empty becomes False. We’re therefore left with:

NOT(False AND the lid is open)

The lid truly is open, so the lid is open is True. Using substitution the lid is open becomes True. We’re therefore left with:

NOT(False AND True)

The AND operator is only True if both assertions on the left and right are True. Therefore False AND True must be False.

NOT(False)

NOT alters an expression to have the opposite value - so what is the opposite of False? - True!

So it ends up being True!

Logic in C#

Now logic is a huge area of mathematics which I’m not really going to explore in this book. I’m only introducing you to what’s necessary to write your fist programs in C#. That said, let’s look at how the above program might be written in C#.

In C#, the primary logic construct is the if statement. An if statement looks something like this:

if (x == 25) {
    Console.WriteLine("Correct!");
}
else {
    Console.WriteLine("Incorrect!");
}

This small program checks if the variable x is equal to 25, using the equality operator. It then prints out a message dependent on the truth of that condition.

The double equals sign == is the C# equality operator. It’s only true if the things on the left and the right have the same value. The Equality operator can be used to compare any sort of data in C#.

The bool type

C# provides a convenient type for storing the result of logical expressions called ‘Boolean’, written bool. A variable of type bool can only ever be true or false.

Let’s start by creating variables to represent the state of the kettle. Let’s start with something to represent if the kettle is empty:

bool theKettleIsEmpty = false;

We declare a variable called theKettleIsEmpty to represent if the kettle is empty. We then assign it a value of false.

A bool can also contain the result of an expression. For instance:

int millilitersOfWaterInKettle = 0;
bool theKettleIsEmpty = kettleContentsInLitres > 0;

Two things are happening here. First we declare a variable, millilitersOfWaterInKettle, to represent the amount of water in the kettle. Next we declare a variable, theKettleIsEmpty of type bool to store the result of a logical expression that determines if the kettle is empty.

The expression uses the ‘greater than’ logical operator, >, which hopefully you should be familiar with from maths lessons at school! It’s true if the value on the left is greater than the value on the right. So, is millilitersOfWaterInKettle greater than 0? Well, millilitersOfWaterInKettle is 0, so no - this evaluates to false.

We can then use the if statement to do something based on the result stored in theKettleIsEmpty:

if (theKettleIsEmpty == true) {
    // Fill up the kettle
}
else {
    // Close the kettle lid
}

First we used the OR operator - we know it’s wrong, but I’m going to show you what it looks like in C# anyway:

if (theKettleIsEmpty == true || theKettleLidIsOpen == true) {
    // Fill up the kettle
}
else {
    // Close the kettle lid
}

The OR operator in C# is represented by two ‘bar’ symbols - ||

Next, let’s say we fix our program to use AND. It would look like this:

if (theKettleIsEmpty == true && theKettleLidIsOpen == true) {
    // Fill up the kettle
}
else {
    // Close the kettle lid
}

The AND symbol is two ampersands - &&

Reference

There are many logical operators in C#. For reference I’m including a list of some of the most commonly used ones. You don’t have to memorize all these at all - in time you’ll just pick them up.

Operator C# Symbol Explanation
AND && Only true if both conditions are true
OR `
EQUALS == Only true if the value on the left is equal to the value on the right
NOT EQUALS != Only true if the value on the left is not equal to the value on the right
NOT ! Negates a value
GREATER THAN > Only true if the value on the left is greater than the value on the right
GREATER THAN OR EQUAL TO >= Only true if the value on the left is greater than or equal to the value on the right
LESS THAN < Only true if the value on the left is less than the value on the right
LESS THAN OR EQUAL TO <= Only true if the value on the left is less than or equal to the value on the right
Copyright Mikiel Agutu 2019