Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
C++ For Dummies (2004) [eng].pdf
Скачиваний:
84
Добавлен:
16.08.2013
Размер:
8.09 Mб
Скачать

48

Part I: Introduction to C++ Programming

decisions. (By the same token, that same property makes a computer look really stupid when the program makes the wrong decision.) Making deci­ sions, right or wrong, requires the use of logical operators.

Using the Simple Logical Operators

The simple logical operators, shown in Table 4-1, evaluate to true or false.

Table 4-1

Simple Operators Representing Daily Logic

Operator Meaning

==Equality; true if the left-hand argument has the same value as the right

!=

Inequality; opposite of equality

>, <

Greater than, less than; true if the left-hand argument is greater

 

than or less than the right-hand argument

 

 

>=, <=

Greater than or equal to, less than or equal to; true if either > or

== is true, OR either < or == is true

&&AND; true if both the left-and right-hand arguments are true

||

OR; true if either the left-or the right-hand argument is true

!

NOT; true if its argument is false

 

 

The first six entries in Table 4-1 are comparison operators. The equality opera­ tor is used to compare two numbers. For example, the following is true if the value of n is 0, and is false otherwise:

n == 0;

Looks can be deceiving. Don’t confuse the equality operator (==) with the assignment operator (=). Not only is this a common mistake, but it’s a mis­ take that the C++ compiler generally cannot catch — that makes it more than twice as bad.

n = 0; // programmer meant to say n == 0

The greater-than (>) and less-than (<) operators are similarly common in everyday life. The following expression logical comparison is true:

Chapter 4: Performing Logical Operations

49

int n1 = 1; int n2 = 2; n1 < n2;

It’s easy to forget which operator is “greater than” and which is “less than.” Just remember that the operator is true if the arrow points to the smaller of the two.

You may think that n1 is greater than or less than n2; however, this ignores the possibility that n1 and n2 are equal. The greater-than-or-equal-to opera­ tor (<=) and the less-than-or-equal-to operator (>=) include that bit of mathe­ matical nuance. They are similar to the less-than and greater-than operators, with one major exception: They include equality; the other operators don’t.

The && (AND) and || (OR) can combine with the other logic operators, like this:

//true if n2 is greater than n1 but n2 smaller than n3

//(this is the most common way determining that n2 is in

//the range of n1 to n3, exclusive)

(n1 < n2) && (n2 < n3);

Storing logical values

The result of a logical operation can be assigned to a variable of type bool:

int n1 = 1; int n2 = 2;

bool b;

b = (n1 == n2);

This expression highlights the difference between the assignment operator = and the comparison operator ==. The expression says, “Compare the vari­ ables n1 and n2. Store the results of this comparison in the variable b.”

The assignment operators are about as low down on the precedence totem pole as you can get. The equality operator is executed before the assignment. The parentheses are not required — so the following is an equally valid form of logical confusion:

b = n1 == n2; // compare n1 with n2; generate a true if n1

//if n1 has the same value as n2, false if not

//store the result, true or false, in b

Whoa. Better look at that again. Note the difference between the operators.

50

Part I: Introduction to C++ Programming

The following program demonstrates the use of a bool variable:

//BoolTest - compare variables input from the

//keyboard and store the results off

//into a logical variable

#include <cstdio> #include <cstdlib> #include <iostream> using namespace std;

int main(int nNumberofArgs, char* pszArgs[])

{

//set output format for bool variables

//to true and false instead

//of 1 and 0 cout.setf(cout.boolalpha);

//initialize two arguments

int nArg1;

cout << “Input value 1: “; cin >> nArg1;

int nArg2;

cout << “Input value 2: “; cin >> nArg2;

bool b;

 

b = nArg1 == nArg2;

 

cout << “The statement, “ << nArg1

<< “ equals “

<< nArg2

<< “ is “

<< b

<<endl;

//wait until user is ready before terminating program

//to allow the user to see the program results system(“PAUSE”);

return 0;

}

The first line cout.setf() makes sure that our bool variable b is output as “true” or “false”. The next section explains why this is necessary.

The program inputs two values from the keyboard and displays the result of the equality comparison:

Input value 1: 5

Input value 2: 5

The statement, 5 equals 5 is true

Press any key to continue . . .

Chapter 4: Performing Logical Operations

51

The special value endl inserts a newline. The difference between the value endl and the character ‘\n’ as described in Chapter 2 is subtle and explained in Chapter 24.

Using logical int variables

C++ hasn’t always had a bool type variable. Back in the old days (before that guy on TV kept walking around saying “Can you hear me now?”), C++ used int variables to store logical values. A value of 0 was considered false and all other values true. By the same token, a logical operator generated a 0 for false and a 1 for true. (Thus, 0 was false while 10 > 5 returned a 1.)

C++ retains a high degree of compatibility between bool and int in order to support the older programs that still have that quirk. You get completely different output from the BitTest program if you remove the line cout. setf(cout.boolalpha):

Input value 1: 5

Input value 2: 5

The statement, 5 equals 5 is 1

Press any key to continue . . .

Variables of type int and bool can be mixed in expressions as well. For exam­ ple, Dev-C++ allows the following bizarre statement without batting an eyelid:

int n;

n = nArg1 == nArg2;

Continue to use type bool to hold logical values despite this wart that modern C++ inherits from its forefathers. Other compilers may not be as forgiving.

Be careful performing logical operations on floating-point variables

Real numbers are those numbers that can have a fractional part. Because of this, real numbers cannot be counting numbers. That is, you can say the first (1st), second (2nd), third, fourth, and so on because the relationship of 1, 2, and 3 are known exactly. It does not make sense to speak of the 4.5th number in a sequence. (This brings to mind the number between the fourth and fifth, but it has no real meaning.)

Similarly the C++ type float, which is the C++ representation, is not a count­ ing number. Even worse (unlike a real number), a floating-point number can’t have an infinite number of digits beyond the decimal point if a computer is

52

Part I: Introduction to C++ Programming

going to make any use of it. Because of this limitation, be careful when you use comparison operators on floating-point numbers. Consider the following example:

float f1 = 10.0; float f2 = f1 / 3;

f1 == (f2 * 3.0); // are these two equal?

The comparison in the preceding example is not necessarily true. A floatingpoint variable cannot hold an unlimited number of significant digits. Thus, f2 is not equal to the number we’d call “three-and-a-third,” but rather to 3.3333..., stopping after some number of decimal places.

A float variable supports about 6 digits of accuracy while a double sup­ ports 13 digits. I say “about” because the computer is likely to generate a number like 3.3333347 due to vagaries in floating point calculations.

Now, in pure math, the number of threes after the decimal point is infinite — but no computer built can handle infinity. So, after multiplying 3.3333 by 3, you get 9.9999 instead of the 10 you’d get if you multiplied “three-and-a-third” — in effect, a round-off error. Such small differences may be unnoticeable to a person, but not to the computer. Equality means exactly that — exact equality.

Modern processors are very sophisticated in performing such calculations. The processor may, in fact, accommodate the round-off error, but from inside C++, you can’t predict exactly what any given processor will do.

Problems can arise even in a straightforward calculation, such as the following:

float f1

=

10.0;

float

f2

=

100 % 30;

f1 ==

f2;

 

// are these two equal?

Theoretically, f1 and f2 should be equal (after you apply that percentlike operator that Chapter 3 identifies as modulus). There doesn’t appear to be any problem with round off. So far. But you can’t be sure — you have no idea how the computer that eventually runs your program is going to represent floating-point numbers internally. To flatly claim that there’s no round-off error lurking here makes unwarranted assumptions about CPU internals.

The safer comparison is as follows:

float f1 = 10.0; float f2 = f1 / 3;

float f3 = f2 * 3.0;

(f1 - f3) < 0.0001 && (f3 - f1) < 0.0001;