3.3 Boolean Variables and Expressions

In summary, the most general form of the IF ... THEN ... ELSIF ... ELSE construction as used in the previous section is as follows:

  IF (Boolean Expression 1)
    THEN
      Statement Sequence 1;
    ELSIF (Boolean Expression 2) THEN
      Statement Sequence 2;
  ...

    ELSIF (Boolean Expression n) THEN
      Statement Sequence n;
    ELSE
      Statement Sequence n + 1;
    END;

All the ELSIFs and the ELSE are optional, depending on the logic required by the program. Note that the form (Boolean Expression i) is used here instead of a specific comparison as in all the examples thus far.

There was a brief discussion of Boolean expressions in section 1.7. The purpose of this section is to specify more exactly what constitute valid boolean expressions in Modula-2, for much more elaborate ones than these can be used in a variety of program structures.

This brings us to the question you may have been ready to ask when you read the heading for this section and the first IF. "What exactly is this thing called a "Boolean expression"? Two related definitions are useful:

An Modula-2 expression is of type BOOLEAN if it can be evaluated unambiguously as "true" or "false".
A Modula-2 variable of type BOOLEAN can have one of the two values TRUE, or FALSE (all three words are standard identifiers).

Previous examples have already illustrated the use of the reserved symbols = and <> (or #) used as comparisons to form boolean expressions and the reserved words OR and AND as connectives to combine two boolean expressions. Here is a complete list of reserved words and symbols for such expressions, together with a translation.

Relational operators

	=		equals
	<		less than
	>		greater than
	<=		less than or equal to
	>=		greater than or equal to
	<> or #		not equal

Other operators (connectives)

	AND or &	both of the conditions must be true
	OR		at least one of the conditions must be true
	NOT or ~	reverses the value of the following logical expression

As in other Modula-2 expressions, any combination of these is allowed, and parentheses can be used to change the natural order of evaluation. Here are a few examples to review the use of these:

Expression                       	BOOLEAN Value

5 <= 5                               	 TRUE
(10 < 5) AND (3 < 4)               	 FALSE
('Y' = 'y') OR FALSE            	FALSE
NOT (5 = 6)                         	 TRUE
(4 = 5) AND ((3 = 7) OR TRUE)        	FALSE

NOTES: 1. The order of evaluation is:

		First	NOT (~)
		Second	*, /, DIV, MOD, AND (&)
		Third	+, -, OR
		Last	the relational operators =, <> (or #), >, >=, <, <=

2. When evaluation reaches an AND, if the left expression is FALSE, the right expression is not evaluated. Likewise, if evaluation reaches an OR, if the left expression is TRUE the right expression is not evaluated. Most computer languages cannot be relied upon to take these shortcuts and may evaluate all parts of every boolean expression. Another more formal way of putting this is to say that if p and q are Modula-2 boolean expressions, then:

p AND q means: IF p THEN q ELSE FALSE

p OR q means: IF p THEN TRUE ELSE q

3. Expressions separated by AND or OR should be enclosed in parentheses. If this is not done, the correct order of evaluation may not be followed, for the statement may not be syntactically correct. If x, y, and z are numbers, then

x < y AND y > z is illegal, but

(x < y) AND (y > z) is correct,

because the compiler would attempt to use the proper order of operations and attempt to interpret the first of these as x < (y AND y) > z which makes no sense at all.

Here are some further examples to illustrate these rules.

Example 1.

(6 DIV 3 + 2 = 5) OR NOT (5 <= 7) & (3 < 10)

would be evaluated as:

(6 DIV 3 + 2 = 5) OR FALSE & (3 < 10)

(2 + 2 = 5) OR FALSE (& not evaluated)

(4 = 5) OR FALSE

FALSE

Example 2.

IF (a < b) OR ((c < d) AND ((y > 0) OR (b - a < 0.05))

Should a in fact be less than b the entire portion on the right of the OR will not be evaluated as the left side alone would be sufficient to give a value of TRUE for the whole expression.

Example 3.

IF (false expression) AND (enormous expression several lines long);

In this case, enormous expression will not be evaluated, again saving considerable time when the code runs.

As indicated above, there are boolean variables in Modula-2 as well as boolean expressions. These are declared like those of any other type, under a VAR heading. They may then be used throughout the program to represent various boolean values. As usual, declaring one of these names does not give it to any particular value--the variable must be initialized before it is known to be either TRUE or FALSE; until then it is undefined. Here is a little program which offers the user a sample choice between two actions and stores the information from the choice in as the value of a boolean variable:

Example 4.

Two groups of students are taking a course in Modula-2 at the same time. The Cmpt141 students have High School computing with high marks and so do a four semester hour course. The Cmpt 143 students attend the same lectures, but have a previous university level course in Pascal. Because it is much easier to learn a second computing notation at this level than a first, these students receive two semester hours credit. They are also exempt from a major assignment. Their marks are calculated as follows:

CMPT 141 CMPT 143

Labs 25% (All must be done to gain credit) 25%

Midterms 30% 35%

Major Paper 10% (essay) Not required

Final Exam 35% 40%

The task is to write a program that will take the percentage marks from the three or four categories and produce a final percentage grade for the course. In what follows, much of the planning has been left out for the sake of brevity.

Pseudocode:

  Print an informative heading
  Initialize the student's totalMark to zero
  Print a prompt asking which course the student is taking
  Set the value of the boolean variable in141 using the answer
  Print a prompt asking if all assignments were handed in
  Set the boolean variable assignOK using the answer
  IF assignOK then
    Print a prompt asking for the lab percentage
    Read the result to the real variable labs
    Set totalMark to 0.25*(labs)
    Print a prompt asking for the midterm percentage
    Read the result to the real variable midterms
    Print a prompt asking for the final exam percentage
    Read the result to the real variable fExam
    If in141 then
      Print a prompt asking for the essay percentage
      Read the result to the real variable essay
      totalMark = totalMark+.3*(midterms)+.35*(fExam)+.1*(essay)
    Else
      totalMark = totalMark+.35*(midterms)+.4*(fExam)
  Print the final mark embedded in a course-specific message
  If Not (assignOK) Then
    Print an explanation

In addition, the code presented here implements a common technique to allow for a repetition of the entire program at the request of the user. This also employs a boolean variable.

MODULE Modula2CourseMarks;

(* Written by R.J. Sutcliffe *)
(* to illustrate the use of Boolean variables *)
(* using P1 Modula-2 for the Macintosh computer *)
(* last revision 1993 02 12 *)

FROM STextIO IMPORT
  WriteString, WriteLn, ReadChar, SkipLine;

FROM SRealIO IMPORT
  ReadReal, WriteFixed;
    
CONST
  labWt = 0.25;
  midtermWt141 = 0.3;
  midtermWt143 = 0.35;
  finalWt141 = 0.35;
  finalWt143 = 0.4;
  essayWt = 0.1;

VAR
  labs, midterms, essay, fExam, totalMark : REAL;
  answer, cr : CHAR;
  in141, assignOk, again : BOOLEAN;

BEGIN
  WriteString ("Modula2CourseMarks written by R.J. Sutcliffe");
  WriteLn;
  WriteString ("as an example in the use of Boolean variables");
  WriteLn;
  WriteLn;
  WriteString ("It computes the final percentage mark for ");
  WriteLn;
  WriteString ("students enrolled in Cmpt 141 and Cmpt 143. ");
  WriteLn;
  WriteLn;
  again := TRUE;
  WHILE again
    DO
      totalMark := 0.0;

      (* Gather the information from the user *)
      WriteString ("Is the student in Cmpt141? Y/N ==> ");
      ReadChar (answer);
      SkipLine;  (* consume the carriage return after the char *)
      WriteLn;
      in141 := (answer = "Y") OR (answer = "y");
      WriteString ("Were all assignments complete? (Y/N) ==> ");
      ReadChar (answer);  (* Note that variables can be re-used *)
      SkipLine;  (* consume the carriage return after the char *)
      WriteLn;
      assignOk := (answer = "Y") OR (answer = "y");
      IF assignOk
        THEN 
          WriteString ("What % mark was earned on labs? ==> ");
          ReadReal (labs);
          SkipLine;  (* consume the carriage return after real *)
          WriteLn;
          totalMark := labWt * labs;
          WriteString ("What was the midterm mark? ==> ");
          ReadReal (midterms);
          SkipLine;
          WriteLn;
          WriteString ("What was the final exam mark? ==> ");
          ReadReal (fExam);
          SkipLine;
          WriteLn;
          IF in141
            THEN
              WriteString ("What mark was the essay mark? ==> ");
              ReadReal (essay);
              SkipLine;
              WriteLn;
              totalMark := totalMark + midtermWt141 * midterms
               + finalWt141 * fExam + essayWt * essay;
            ELSE
              totalMark := totalMark + midtermWt143 * midterms
               + finalWt143 * fExam;
            END; (* if in141 *)
        END; (* if assignOk *)
          
      (* print the result *)
      WriteString ("The final mark for Cmpt");
      IF in141
        THEN
          WriteString (" 141 ");
        ELSE
          WriteString (" 143 ");
        END;
      WriteString (" was ");
      WriteFixed (totalMark, 2, 0);
      WriteString ("%.");
      WriteLn;
      IF NOT assignOk
        THEN
          WriteString ("No credit when assignments not done.");
          WriteLn;
        END;

      WriteLn;
      WriteString ( "Do another calculation? Y/N ==> ");
      ReadChar (answer);
      again := (answer = "Y") OR (answer = "y");
      SkipLine;
      WriteLn;
    END; (* of the while loop *)

END Modula2CourseMarks.

Here is a run from this module:

Modula2CourseMarks written by R.J. Sutcliffe
as an example in the use of Boolean variables

It computes the final percentage mark for 
students enrolled in Cmpt 141 and Cmpt 143. 

Is the student in Cmpt141? Y/N ==> Y
Were all assignments complete? (Y/N) ==> Y
What % mark was earned on labs? ==> 100
What was the midterm mark? ==> 90
What was the final exam mark? ==> 85
What mark was the essay mark? ==> 72.5
The final mark for Cmpt 141  was  89.00%.

Do another calculation? Y/N ==> Y
Is the student in Cmpt141? Y/N ==> N
Were all assignments complete? (Y/N) ==> N
The final mark for Cmpt 143  was  0.00%.
No credit when assignments not done.

Do another calculation? Y/N ==> N

In programs like this, one sets a boolean from keyboard input and then uses the value one or more times to determine which course to take through the code.

When the value of a boolean variable is used one or more times to determine the appropriate path through a program, the variable is called a flag.

NOTE: It is redundant, superfluous, and too much excess of unnecessary extra code to write IF assignOk = TRUE when it suffices to use IF assignOk.


Contents