How does Boolean work in C.

"What is truth?"
Pontius Pilatus (Joh. 18, 38)

Conditions were already used in the query and in the question mark expression. Conditions are also used in the loops, so it is time to take a closer look at them.

heritage

The result of a condition can have two states: it can be true or false. For the true state, C ++ uses the keyword, and for false it is. The C language did not know these two keywords, but interpreted the numerical value 0 as wrong and every other numerical value as correct. C ++ inherited this behavior, so both 0 stands for false.

Variables and constants

Type bool

Since C ++ knows its own constants for the truth values, it is also obvious that there is a separate data type for them. This bears the name and can accept the values ​​or. Although theoretically only one bit is required for such a variable, in practice it occupies at least one byte. bool smaller = true; Smaller = a Operators

Bigger and smaller

The easiest way to formulate a condition is to compare two numerical values ​​with one another. To inquire whether the first number is smaller than the second, a less than sign () is placed between the operands. As a donkey's bridge, you can imagine that the less than sign was formed from an equal sign by reducing the distance between the two lines on the left (in the reading direction at the beginning). Another donkey bridge works via the German keyboard. The larger and smaller characters are on the same key. To get the greater than sign you have to press the key with which you also create upper case letters. if (a a smaller than the content of b is.

By adding an equal sign, the less than or equal to sign can be made, which queries whether the left value is "less than or equal to" the right value.

if (a <= b) To generate the greater than or equal sign, the greater than or equal to sign must first be set and then the equal sign. There must be no space between the two.

equal

To query the equality between two values, C ++ uses two directly consecutive equal signs. This is necessary to distinguish it from the assignment symbol. if (a == b) The following statement is only executed if the content of the variable a and the content of b is equal to. Unfortunately, there is a nasty trap lurking here. Take a look at the following code: if (a = 1) // watch out, trap! {a = 5; } At first glance, it looks like the variable a A 5 is assigned if and only if the content of the variable a would be equal to 1. In fact, a = 1 is an assignment. The variable a so contains the value 1 after executing the statement. That was probably not what the programmer wanted. In addition, the result of the content in brackets is also 1 because the assignment value is always passed to the left. However, since a number other than 0 is always interpreted as true, the condition is always true and the assignment is always carried out. Correctly it has to read: if (a == 1) {a = 5; } Because of the particularly insidious nature of this situation, most compilers respond with a warning if the condition contains an assignment. It is not a mistake, because due to its C heritage, it is perfectly permissible in C ++ to use numerical values ​​as Boolean values. Some programmers have made it a habit to use the constant first when making queries, because a == 1 is the same as 1 == a. However, if you forget the second equal sign, 1 = a immediately results in a compiler error. On the other hand, it can be assumed that a programmer who thinks about writing the query down in this form also thinks about adding a second equal sign.

Unequal

The inequality sign is an exclamation mark followed by an equal sign. The exclamation mark represents the sign for the negative.

Comparison of numerical values

operator importance
a == b a equal to b?
a! = b a not equal to b?
a> b a greater than b?
a> = b a greater than or equal to b?
a a smaller than b?
a <= b a less than or equal to b?

You can only ever compare two operands with one another. If you want to check the value of the variable a is between 5 and 10, this must be done in two comparisons. The following query is allowed by the compiler, but gives a completely different interpretation:

if (5 <= a <= 10) // does not work! {// do anything; } First, the compiler will evaluate the expression. (For the experts: The comparison operators are left-associative.) This can be true or false, so results in 0 or 1. This value is now linked to. Since 0 and 1 are less than 10, the above expression as a whole will always be true. It must be compared correctly whether a is greater than or equal to 5 and whether a is less than or 10. if (5 <= a) {if (a <= 10) {// do something; }} The expressions are now linked in such a way that both expressions must match in order to reach the inner block.

Linking Boolean expressions

AND

If two conditions have to be met for the overall condition to be true, then one speaks of an AND operation. Example: If a value is to lie within an interval, it must meet two conditions: The value must at least reach the minimum and must not exceed the maximum. Both partial conditions must be fulfilled for the overall condition to be true. This link is called AND and is represented in C ++ with two ampersands. if (5 <= a && a <= 10) {// do something; } Another example: A company may only pay out Christmas bonuses if the employee is a permanent employee and has been with the company for six months. Here, too, both conditions must be met. So it is also an AND link. The following truth table shows all possible combinations of the two operands and the result of the AND operation:
a b a && b
true true true
true false false
false true false
false false false

OR

It's another thing to do when you want to check whether a value is outside of an interval. The value can badly be both greater than the maximum and less than the minimum. The AND connection is nonsense here. It will be sufficient that either condition is met. If the value is smaller than the minimum of the interval, it is already outside. The partial condition that the value is above the maximum is also sufficient for the value to be outside the interval. A link that is true if one of the partial conditions is true is called an OR link and is represented by two vertical lines. (In most fonts, these vertical bars have a gap in the middle.) If (5> a || a> 10) {// Do something; } To our other example: A somewhat more generous company could follow the rule that both employees from the first day of service and temporary workers who have been with the company for more than two years receive Christmas bonuses. In this case, the fulfillment of a partial condition would be sufficient to fulfill the overall condition. The OR link is used here.

Truth table OR

a b a || b
true true true
true false true
false true true
false false false

NOT

The third logical operator negates a Boolean value. The NOT or NOT affects an operand and is represented in C ++ by the exclamation mark. If the expression preceded by the exclamation mark is true, the overall expression is false.

Truth table NOT

a ! a
true false
false true

Linguistic inaccuracy

Pay close attention to the definition of the AND and OR links. AND is fulfilled if all partial conditions are true. OR is fulfilled if at least one of the partial conditions is fulfilled. The linguistic usage is often much more sloppy. For example, if you see a sign in a museum that roller skating and eating ice cream are prohibited, then from the point of view of Boolean algebra you should definitely be roller skating. You are also allowed to eat ice cream. You just shouldn't do both. However, you will probably not be able to convince any of the supervisors with this. You should rather expect that their mathematical knowledge is not so strong, but that they are worried about the exhibits. In the colloquial area, the OR link is quickly tightened to an either-or. The difference is that OR is true if at least one subexpression is true. Either-or, on the other hand, states that exactly one partial expression is true.

XOR

C ++ does not provide its own Boolean operator for the either / or link. Such a link is often also called XOR. Of course it is possible to simulate this operator with the help of AND and OR. To do this, first create a table in which you record when the link becomes true and when it becomes false:

Truth table either or

a b a XOR b
true true false
true false true
false true true
false false false

There are two ideas how you can find the solution. The first idea is to replicate all lines that are true and to combine these replicas with OR. In the example these are the two middle lines. The first line is "a AND NOT b" because a is true and b is false. The second line is "NOT a AND b". Finally, the two expressions are combined with OR. You can create a truth table for control purposes:

Truth table (a AND NOT b) OR (NOT a AND b)

a b a &&! b ! a && b (a &&! b) || (! a && b)
true true false false false
true false true false true
false true false true true
false false false false false

The second idea tries to sum up all the true lines. If a few wrong lines are included, you just have to exclude them again. In the example, "a OR b" would span the top three lines. Only the first line does not match "a XOR b", so you exclude it with "AND NOT". The expression then reads: "(a OR b) AND NOT (a AND b)". Here, too, the truth table proves whether the expression is correct:

Truth table (a OR b) AND NOT (a AND b)

a b a || b a && b (a || b) &&! (a && b)
true true true true false
true false true false true
false true true false true
false false false false false

And then there are practical approaches to simulating an XOR operator. The not equal operator can be used as a Boolean operator. Alternatively, the binary operator ^ can be used. Since the Boolean expression is compatible with numbers, it also works like a Boolean operator when combining Boolean expressions.

De Morgan

Negate expressions

There may be some surprises when negating linked expressions. Indeed, according to De Morgan's law, the following rules apply:! (a && b) is equivalent to! a || ! b! (a || b) is equivalent to! a &&! b As an example, we want to negate a query that checks whether a value lies within an interval. The result of the negation would therefore be a query as to whether the value lies outside the interval. Since you have already seen both queries, you can easily check the step of negation in this example. if (a> = 2 && a <= 5) The simplest way to form the negation is to put a bracket around the overall expression and to negate its content with the exclamation mark. if (! (a> = 2 && a <= 5)) That may seem unsportsmanlike, but it is without question correct. That is why you should rather use such a less elegant solution than an elegant one that has the blemish of being wrong. It would be wrong, for example, to simply reverse the comparison operators: if (a <2 && a> 5)) // fast, but wrong! Here it would be checked whether the variable a is both less than 2 and greater than 5. Obviously, a value cannot be both. If, on the other hand, you apply De Morgan's rule, the partial expressions are negated and AND is replaced by OR: if (! (A> = 2) ||! (A <= 5)) Now the partial expressions can be simplified: is easy to be converted into. Exactly is equivalent to. So the correctly implemented condition is: if (a <2 || a> 5)) // correct negation! The variable a falls outside the interval if it is less than 2 or greater than 5. If either statement is true, the overall expression is true. Lies a but in the interval, both partial expressions are wrong, and thus the total expression is also wrong. The result is that an AND link is negated by negating each partial expression and replacing the AND with an OR. The same applies in reverse: To negate an OR link, the partial expressions are negated and the OR is replaced by an AND.

Short circuit

One for all

When processing linked conditions, the program does not have to evaluate all partial conditions in every case. If, for example, the first partial condition fails with an AND link, it is not necessary to check the other partial conditions, because the overall expression can only be wrong. The same applies if the first partial expression already turns out to be true in the case of an OR link. Then the other partial conditions no longer need to be checked. The overall expression must be true.

This knowledge is implemented in C ++ to increase efficiency. In such a situation, the program will stop further analysis and immediately draw its conclusions. In the vast majority of cases, this behavior will hardly affect you. You probably won't even notice the slight gain in speed. It becomes more difficult, however, if the second partial expression does something else besides finding the truth.

if ((Salary <2000) && (PersonalNr ++> 10)) {... Normally, after running through this query, the variable Personal No increased by one. In fact, this is by no means the case if the salary is less than 2000. So it should be intended that the variable Personal No is incremented, the order of the conditions must be reversed. if ((PersonalNr ++> 10) && (Salary <2000)) {... However, it makes much more sense to avoid such situations as a matter of principle. Queries and their links should be within a condition. To be on the safe side, you should put arithmetic and other operations before or after the condition. PersonalNr ++; if ((PersonalNr> 10) && (Salary <2000)) {...