1. Trang chủ
  2. » Công Nghệ Thông Tin

Smooth Operators

14 158 0
Tài liệu đã được kiểm tra trùng lặp

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Tiêu đề Smooth operators
Thể loại Chapter
Định dạng
Số trang 14
Dung lượng 397,47 KB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

Table 4-1 The Simple Operators-unary Take the negative of Most of these operators are called binary operators because they operate on two values: one on the left side of the operator and

Trang 1

Chapter 4 Smooth Operators

In This Chapter

Performing a little arithmetic

Doing some logical arithmetic

Complicating matters with compound logical operators

Mathematicians create variables and manipulate them in various ways, adding them, multiplying them, and — here’s a toughie — even integrat-ing them Chapter 3 describes how to declare and define variables However, it says nothing about how to use variables to get anything done after you’ve declared them This chapter looks at the operations you can perform on

vari-ables to actually get something done Operations require operators, such as +,

-, =, <, and & I cover arithmetic, logical, and other operators in this chapter Writing programs that get things done is good You’ll never make it as a C# programmer if your programs don’t actually do something — unless, of course, you’re a consultant

Performing Arithmetic

The set of arithmetic operators breaks down into several groups: the simple arithmetic operators, the assignment operators, and a set of special opera-tors unique to programming After you’ve digested these, you also need to

digest a separate set of logical operators Bon appétit!

Simple operators You learned most of the simple operators in elementary school Table 4-1

lists them Note: Computers use an asterisk (*) for multiplication, not the

multiplication sign (×)

Trang 2

Table 4-1 The Simple Operators

-(unary) Take the negative of

Most of these operators are called binary operators because they operate on

two values: one on the left side of the operator and one on the right side The one exception is the unary negative However, this one is just as straightfor-ward as the others, as I show in the following example:

int n1 = 5;

int n2 = -n1; // n2 now has the value -5

The value of -nis the negative of the value of n The modulo operator may not be quite as familiar to you Modulo is similar

to the remainder after division Thus, 5 % 3is 2 (5 / 3 = 1, remainder 2), and

25 % 3is 1 (25 / 3 = 8, remainder 1) Read it “five modulo three” or simply

“five mod three.”

The strict definition of % is “the operator such that: x = (x / y) + x % y.” Divide

xby y Add xmodulo y(which equals the remainder after x / y) The result

is x The arithmetic operators other than modulo are defined for all the numeric types The modulo operator is not defined for floating point numbers because you have no remainder after division of floating point values

Operating orders The value of some expressions may not be clear Consider, for example, the following expression:

int n = 5 * 3 + 2;

Does the programmer mean “multiply 5 times 3 and then add 2,” which is 17, or does this line mean “multiply 5 times the sum of 3 and 2,” which gives you 25?

Trang 3

C# generally executes common operators from left to right So, the preceding example assigns the value 17 to the variable n

C# determines the value of nin the following example by first dividing 24 by 6 and then dividing the result of that operation by 2 (as opposed to dividing 24

by the ratio 6 over 2):

int n = 24 / 6 / 2

However, the various operators have a hierarchy, or order of precedence C#

scans an expression and performs the operations of higher precedence before those of lower precedence For example, multiplication has higher precedence than addition Many books take great pains to explain the order

of precedence, but frankly that’s a complete waste of time (and brain cells)

Don’t rely on yourself or someone else knowing the precedence order Make your meaning (to human readers of the code as well as to the compiler) explicit with parentheses

The value of the following expression is clear, regardless of the operators’

order of precedence:

int n = (7 % 3) * (4 + (6 / 3));

Parentheses can override the order of precedence by stating exactly how the compiler is to interpret the expression C# looks for the innermost parentheses for the first expression to evaluate, dividing 6 by 3 to yield 2 The result follows:

int n = (7 % 3) * (4 + 2); // 2 = 6 / 3

Then C# works its way outward, evaluating each set of parentheses in turn, innermost to outermost, as follows:

int n = 1 * 6; // 6 = (4 + 2)

And here’s the final result:

int n = 6

The “always use parentheses” rule has perhaps one exception I don’t con-done this behavior, but many programmers omit parentheses in examples like the following, because multiplication has higher precedence than addi-tion Consider the following example:

int n = 7 + 2 * 3; // same as 7 + (2 * 3)

In this case, the value of the variable nis 13 (not 27)

Trang 4

The assignment operator C# has inherited an interesting concept from C and C++: Assignment is itself a binary operator The assignment operator has the value of the argument to the right The assignment has the same type as both arguments, which must match

This new view of the assignment operator has no effect on the expressions you’ve seen so far:

n = 5 * 3;

In this example, 5 * 3 is 15 and an int The assignment operator stores the

inton the right into the inton the left and returns the value 15 However, this new view of the assignment operator allows the following:

m = n = 5 * 3;

Assignments are evaluated in series from right to left The right-hand assign-ment stores the value 15 into nand returns 15 The left-hand assignment stores 15 into mand returns 15, which is then dropped on the floor, leaving the value of each variable as 15

This strange definition for assignment makes the following rather bizarre expressions legal (but I would avoid this):

int n;

int m;

n = m = 2;

I avoid chaining assignments that way because it’s less clear to human readers Anything that can confuse people reading your code (including you) is worth avoiding because confusion breeds errors A huge proportion of computer pro-gramming, from language rules and constructs to naming conventions and rec-ommended programmer practices, is devoted to fighting error Join the fight C# extends the simple operators with a set of operators constructed from other binary operators For example:

n += 1;

This expression is equivalent to the following:

n = n + 1;

An assignment operator exists for just about every binary operator I’m really not sure how these various assignment operators came to be, but there they are Table 4-2 shows the most common compound assignment operators

Trang 5

Table 4-2 Common Compound Assignment Operators

a += b Assign a + b to a

a -= b Assign a - b to a

a *= b Assign a * b to a

a /= b Assign a / b to a

a %= b Assign a % b to a

a &= b Assign a & b to a (& is a logical operator, discussed later)

a |= b Assign a | b to a (| is a logical operator)

a ^= b Assign a ^ b to a (^ is a logical operator)

Table 4-2 omits a couple of advanced compound assignment operators, <<=

and >>= I mention the “bit-shifting” operators later in the chapter

The increment operator

Of all the additions that you may perform in programming, adding 1 to a vari-able is the most common, as follows:

n = n + 1; // increment n by 1

Why have an increment operator?

The reason for the increment operator lies in the obscure fact that the PDP-8 computer of the 1970s had an increment instruction This would

be of little interest today were it not for the fact that the C language, the original precursor to C#, was originally written for the PDP-8 Because that machine had an increment instruction, n++

generated fewer machine instructions than n =

n + 1 As slow as those machines were, saving

a few machine instructions was a big deal

Today, compilers are smarter and no difference exists in the execution time for n++and n = n + 1, so the increment operator is no longer

needed However, programmers are creatures

of habit, and the operator remains to this day

You almost never see a C++ programmer incre-ment a value using the longer but more intuitive

n = n + 1 Instead, you see the increment operator

Further, when standing by itself (that is, not part

of a larger expression), the postincrement oper-ator almost always appears instead of the preincrement operator There’s no reason other than habit and the fact that it looks cooler, espe-cially to C++ programmers: n++

Trang 6

C# defines the assignment operator shorthand as follows:

n += 1; // increment n by 1

Even that’s not good enough C# provides this even shorter version:

++n; // increment n by 1

All three of the preceding statements are equivalent — they all increment n

by 1

The increment operator is strange enough, but believe it or not, C# has two increment operators: ++nand n++ The first one, ++n, is called the

preincre-ment operator, while n++is the postincrement operator The difference is

subtle but important

Remember that every expression has a type and a value In the following code, both ++nand n++are of type int:

int n;

n = 1;

int p = ++n;

n = 1;

int m = n++;

But what are the resulting values of mand p? (Hint: The choices are 1 or 2.) The value of pis 2, and the value of mis 1 That is, the value of the expression

++nis the value of nafter being incremented, while the value of the

expres-sion n++is the value of nbefore it is incremented Either way, the resulting

value of nis 2

Equivalent decrement operators — that is, n and n— exist to replace n

= n – 1 These work in exactly the same way as the increment operators

Performing Logical Comparisons —

Is That Logical?

C# also provides a set of logical comparison operators, as shown in Table 4-3

These operators are called logical comparisons because they return either a

trueor a falseof type bool

Trang 7

Table 4-3 The Logical Comparison Operators

Operator Operator Is True If

a == b a has the same value as b

a > b a is greater than b

a >= b a is greater than or equal to b

a < b a is less than b

a <= b a is less than or equal to b

a != b a is not equal to b

Here’s an example that involves a logical comparison:

int m = 5;

int n = 6;

bool b = m > n;

This example assigns the value falseto the variable bbecause 5 is not greater than 6

The logical comparisons are defined for all numeric types, including float,

double, decimal, and char All the following statements are legal:

bool b;

b = 3 > 2; // true

b = 3.0 > 2.0; // true

b = ‘a’ > ‘b’; // false - alphabetically later = greater

b = ‘A’ < ‘a’; // true - upper A is less than lower a

b = ‘A’ < ‘b’; // true - all upper are less than all lower

b = 10M > 12M; // false

The comparison operators always produce results of type bool The compar-ison operators other than ==are not valid for variables of type string (Not

to worry; C# offers other ways to compare strings.)

Comparing floating point numbers:

Is your float bigger than mine?

Comparing two floating values can get dicey, and you need to be careful with these comparisons Consider the following comparison:

Trang 8

float f1;

float f2;

f1 = 10;

f2 = f1 / 3;

bool b1 = (3 * f2) == f1;

f1 = 9;

f2 = f1 / 3;

bool b2 = (3 * f2) == f1;

Notice that the fifth and eighth lines in the preceding example each contain first an assignment operator (=) and then a logical comparison (==) These are different animals C# does the logical comparison and then assigns the result to the variable on the left

The only difference between the calculations of b1and b2is the original value of f1 So, what are the values of b1and b2? The value of b2is clearly

true: 9 / 3 is 3; 3 * 3 is 9; and 9 equals 9 Voilà!

The value of b1is not so obvious: 10 / 3 is 3.333 3.333 * 3 is 9.999 Is 9.999 equal to 10? That depends on how clever your processor and compiler are On a Pentium or later processor, C# is not smart enough to realize that b1

should be trueif the calculations are moved away from the comparison You can use the system absolute value function to compare f1and f2as follows:

Math.Abs(f1 - 3.0 * f2) < 00001; // use whatever level of accuracy

This function returns truefor both cases You can use the constant

Double.Epsiloninstead of 00001 to get the maximum level of accuracy

Epsilonis the smallest possible difference between two nonequal double

variables

For a self-guided tour of the System.Mathclass, where Absand many other

useful mathematical functions live, choose Help➪Index and type Math in the

Look For box

Compounding the confusion with compound logical operations

The boolvariables have another set of operators defined just for them, as shown in Table 4-4

Trang 9

Table 4-4 The Compound Logical Operators

Operator Operator Is True If

!a a is false

a & b a and b are true

a | b Either a or b or else both are true (also known as a and/or b)

a ^ b a is true or b is true but not both (also known as a xor b)

a && b a is true and b is true with short-circuit evaluation

a || b a is true or b is true with short-circuit evaluation (I discuss

short-circuit evaluation in the nearby text.)

The !operator is the logical equivalent of the minus sign For example, !a

(read “not a”) is true if ais false and false if ais true Can that be true?

The next two operators are straightforward enough First, a & bis only true

if both aand bare true And a | bis true if either aor bis true (or both)

The ^(also known as exclusive or — xor) operator is sort of an odd beast An

exclusive or is true if either aor bis true but not if both aand bare true

All three operators produce a logical boolvalue as their result

The &, |, and ^operators also have a bitwise operator version When applied

to intvariables, these operators perform their magic on a bit-by-bit basis

Thus, 6 & 3 is 2 (01102& 00112is 00102), 6 | 3 is 7 (01102| 00112is 01112), and

6 ^ 3 is 5 (01102^ 00112is 01012) Binary arithmetic is really cool but beyond the scope of this book

The remaining two logical operators are similar to, but subtly different from, the first three Consider the following example:

bool b = (boolExpression1) & (boolExpression2);

In this case, C# evaluates boolExpression1and boolExpression2 It then looks to see whether they are both true before deciding the value of b However, this may be a wasted effort If one expression is false, there’s no reason to perform the other Regardless of the value of the second expres-sion, the result will be false

The &&operator enables you to avoid evaluating both expressions unneces-sarily, as shown in the following example:

bool b = (boolExpression1) && (boolExpression2);

Trang 10

In this case, C# evaluates boolExpression1 If it’s false, bis set to false and the program continues on its merry way On the other hand, if boolExpression1is true, C# evaluates boolExpression2and stores the result in b

The &&operator uses short-circuit evaluation because it short-circuits around

the second boolean expression, if necessary

The ||operator works the same way, as shown in the following expression:

bool b = (boolExpression1) || (boolExpression2);

If boolExpression1is true, there’s no point in evaluating boolExpression2

because the result is always true

You can read these operators as “short-circuit and” and “short-circuit or.”

Finding the Perfect Date — Matching Expression Types

In calculations, an expression’s type is just as important as its value

Consider the following expression:

int n;

n = 5 * 5 + 7;

My calculator says the resulting value of nis 32 However, that expression also has a type

Written in “type language,” the preceding expression becomes the following:

int [=] int * int + int;

To evaluate the type of an expression, follow the same pattern you use to evaluate the expression’s value Multiplication takes precedence over addi-tion An inttimes an intis an int Addition comes next An intplus an int

is an int In this way, you can reduce the preceding expression as follows:

int * int + int int + int int

Ngày đăng: 04/10/2013, 21:20

Xem thêm

TÀI LIỆU CÙNG NGƯỜI DÙNG

  • Đang cập nhật ...

TÀI LIỆU LIÊN QUAN

🧩 Sản phẩm bạn có thể quan tâm

w