Booleans (Part 4)
Example: determining if a number is even
Let's use Booleans to create a function that determines whether or not a given number is even.
Function definition recipe
- Choose function and parameter names.
- Choose the types of the parameters and the type of the output (if any).
- Write the function header, which specifies the names.
- Write the function body, the code for the function.
We will write a function that consumes an integer and produces a Boolean. We use even as the name of the function and num as the name of the parameter, and return the outcome of the comparison between floor(num/2) and num/2:
Function: even
Parameter: num
Input: integer
Output: Boolean
The function can be written as define even(num) return floor(num / 2) == num / 2
Another option would have been to use ceiling, or the modulo function, where we want the remainder on dividing by 2 to be 0: return ceiling(num / 2) == num / 2 return modulo(num, 2) == 0
Example: offpeak usage
As another example, suppose we want to figure out whether a particular time is eligible for offpeak rates, that is, it is not between 9 am and 5 pm. We'll use 24-hour time, so offpeak means not between 9 and 17. Accordingly, we'll assume our input is an integer in the range from 0 to 23. We choose the name "offpeak" for our function and the name "hour" for our parameter:
Function: offpeak
Parameter: hour
Input: integer from 0 to 23
Output: Boolean
Now we can write the function: define offpeak(hour) early ← hour < 9 late ← hour > 17 return (early or late)
Extending the inputs
What if we didn't trust users to restrict inputs to integers from 0 to 23? We could change the input to "any" (that is, we allow any data type) and check that we have an integer:
Function: offpeak
Parameter: hour
Input: any
Output: Boolean
Since many languages have built-in functions to check for type, we'll assume that our pseudocode has a function is_integer that returns True when the input is an integer. We use the same function header, but now compute not only early and late, but also a variable good, where we want good to be true as well as at least one of early and late: define offpeak(hour) good ← is_integer(hour) early ← hour < 9 late ← hour > 17 return (good and (early or late))
But if hour is not a number, there will be an error when early is being computed, since the less than operation requires two numbers.
Let's try again, this time taking advantage of shortcut evaluation. Here, we use the same idea as above, but we write one long expression for the value returned: define offpeak(hour) return (is_integer(hour) and ((hour < 9) or (hour > 17)))
Evaluating the condition
Notice that we have three smaller expressions:
is_integer(hour) and ((hour < 9) or (hour > 17))
The second and two are joined by an or, and the first is joined to that expression by an and. We will be making use of short-cut evaluation for both and and or.
Example 1:
Suppose that the value of hour is the integer 3. We would evaluate the first expression to obtain True: is_integer(hour) evaluates to True.
Can we stop early? No, since this is an expression joined by and, and for and, we can only stop early if we see a False expression. So we need to evaluate the second expression, hour < 9. It is True and joined by or to the third expression, so we can stop before evaluating the last smaller expression. That is, we know that both the expressions joined by and are True, and hence the entire expression is True.
Example 2:
Now lets assume that the value of hour is the integer 9. Again the first expression, is_integer(hour), is True, so again we can't stop early. What about the second expression, hour < 9? Since it is False, can we stop early? No, since it alone is not one of the expressions joined by the and. It is part of the expression formed using or, which means that to stop early it would have to be True. So we need to evaluate the third expression, hour > 17. It turns out to be False, which means that we have True and the expression False or False, that is, True and False, which evaluates to False.
Example 3:
For input 18, again the first expression, is_integer(hour), is True, so we can't stop early, and the second expression, hour < 9, is False, so we can't stop early. Finally the third expression, hour > 17, is True, so that the condition evaluates to True.
Example 4:
When the input is not an integer, the first expression, is_integer(hour), evaluates to False. Since it is joined with an and, we can stop early and conclude that the entire expression is False. The key idea is that since we stop early, we never compare cat to 9 or 17, and hence there is no error.