Lemur zaprasza
What You'll Learn About Reviewing the Basics The Unary Operators Two Divisions and Remainder Order of Operators Advanced Assignments Multiple Assignments Compound Operators Homework General Knowledge What's the Output? Find the Bug Write Code That. . . Extra Credit - 7 - Fundamental Math Operators associativity math operators overloaded operators operator precedence unary operators What You'll Learn About Reviewing the basics Order of operators Advanced assignments Although you've seen the four primary math operators (+, -, *, and /), there are several more. Appendix C, "Visual C++ Operator Precedence Table," lists all of Visual C++'s operators. C++ is a language rich in operators. Not all of them are math-related, but many are. In this unit, you'll learn about several of the math operators and become more acquainted with the operator precedence that is so important in Visual C++. Appendix C's operator table not only describes each of the operators, but it also lists each operator in order of its precedence over other operators. As you might recall from Lesson 2, some operators execute before others, such as division before addition. Although Visual C++ computes all your math results for you, you still must understand how to set up your calculations to achieve correct results. If you never thought math was fun, that's okay. There's a lot more to Visual C++ programming than math. However, programs are extremely useful for computing sales figures, inventory totals, and much more, relieving you from those tedious burdens. Knowing how to use Visual C++'s operators will let you set up your programs so that you can toss that pocket calculator out the window. Reviewing the Basics The primary math operators do what you expect them to. When you need simple arithmetic, the primary math operators will compute many of your needed answers. Although you understand basic addition, subtraction, multiplication, and division, Visual C++ presents a few extra considerations that you need to understand. The following sections explore the primary math operators, shown in Table 7.1. Table 7.1. Visual C++'s primary math operators. Math Operator Description * Multiplication / Division or integer division % Modulus (also called remainder) + Unary: Specifies a positive amount (optional for positive values) Binary: Performs addition - Unary: Specifies a negative amount Binary: Performs subtractiondefinition An overloaded operator performs more than one operation depending on how you use it. Notice that some of the operators are overloaded. For example, the division operator either performs regular division as you know it (sometimes called floating-point division) or computes integer division under certain circumstances. The following sections describe the dual operations of +, -, and /. The Unary Operators definition A unary operator operates on a single value. The unary operators, + and -, are almost too obvious to discuss because they're so easy to understand. However, they do appear in different locations in the precedence table than their binary counterparts, so they warrant their own discussions. The term binary operator has nothing to do with binary numbers. Whereas a unary operator operates on single values, binary operators operate on two values (bi is a prefix meaning two). Anytime you put a plus sign in front of a single numeric literal or variable, the plus sign operates as a unary plus sign. The plus sign is optional. Both of the following statements are equivalent: ageLimit = 18; // Put a positive 18 in a variable and ageLimit = +18; // Put a positive 18 in a variable You can place the unary plus in front of variables: newLimit = +ageLimit + 3; // Raise the old age limit Be careful when putting plus signs together. If you rearrange the previous assignment to be newLimit = 3 + +ageLimit; // Raise the old age limit Visual C++ won't care and everything will work fine, but the space between the two plus signs is critical. Without the space, C++ will complain via a compile error. The ++ (two plus signs without a space between them) is another C++ operator that you'll learn about in the next lesson. Again, the unary plus sign is very obvious and is one of the easiest operators to understand. The unary plus sign is also optional because if you omit it, C++ assumes that the literal or variable is a positive value. If you want to negate a variable or specify a negative numeric literal, use the unary minus sign. The following statement stores a negative value in a variable: rateOfGrowth = -.23; You can negate (take the negative of) a variable's value like this: factor = amount * -value; value does not change in this statement. value is one of the rvalues, and only lvalues (factor in this case) change as a result of assignment statements. This statement tells Visual C++ the following: "Multiply the value in amount by the negative of the number in value and store that computed result in factor. Don't change either amount or value from their old values; change only factor." C++ distinguishes between variables that are on the left and right sides of the equal sign. All values can be rvalues, which is a variable on the right side of the equal sign. An rvalue only needs to provide a value. Not all values can be lvaluesnumbers on the left side of the equals signbecause not all values can have new values assigned into them. Generally, you don't need to worry about the rvalue and lvalue concept, but you will see it in error messages. Feel free to negate any mathematical expression such as the following: a = -(b * c); The quantity b multiplied by c is computed, and then the negative of that quantity is stored in a. Again, neither b nor c changes due to the assignment. As with the unary plus sign, be sure to put a space before the unary minus sign: a = b - -c; // Without the space, strange things would happen! In the preceding statement, the first negative sign is a binary subtraction and the second (the minus before c) is a unary minus. See the difference? As stated before, binary operators operate on two values, while a unary operator operates on only one value. Two Divisions and Remainder The division operator, /, performs mathematical division, with the value before the operator being divided by the value following the operator. The operation of division works in a different way depending on whether all the values are integers or not. If both values are integers, the result of the division will be an integer value too. If either operand is a real value (remember a real value is one that holds decimal places), the result will be a real value. It is important to note that it is not the type of the answer variable that determines the type of the result. Let's look at an example to see how this works in practice. The program in Listing 7.1 contains an integer division operator. It's an integer division operator because an integer appears on both sides of the /. The programmer was hoping to get a more accurate value. Unit 9, "Special Operations," explains how you can change an integer value into a real value to force a real division. Listing 7.1. Performing integer division. // Filename: INTDIV.CPP // Computes integer division #include <iostream.h> void main() { int people, events; float avgEv; cout << "How many people will attend? "; cin >> people; cout << "How many events are scheduled? "; cin >> events; // Compute the average number of people per event avgEv = people / events; // The integer division ensures // that the fractional part of // the answer is discarded cout << "There will be an average of " << avgEv << " people per event." << endl; return; } Here is a sample run of the program: How many people will attend? 14 How many events are scheduled? 3 There will be an average of 4 people per event. If an integer variable, literal, or a combination of the two appears on both sides of the /, the / always computes integer division. If a noninteger appears on one or both sides of the division operator, Visual C++ computes normal fractional division. For example, the following statement stores 10.5 in a float variable named ans: ans = 21.0 / 2; // Stores 10.5 in ans Each of the following assignment statements also stores 10.5 in ans (notice the different decimal-point placements): ans = 21 / 2.0; // Stores 10.5 in ans and ans = 21.0 / 2.0; // Stores 10.5 in ans Do the division operator and the comment slashes confuse you because of their similarity? Of course, you can tell them apart, but perhaps in these statements the regular C-style comments would be a little less confusing: ans = 21.0 / 2.0; /* Stores 10.5 in ans */ Table 7.1 showed the modulus (or remainder) operator, %. The modulus operator performs the opposite of the integer division operator: Instead of returning the integer answer and discarding the remainder, the modulus operator returns the remainder and discards the integer division answer. Don't use % on floating-point values. % returns the remainder of integer division only. The following statement stores 1 in ans: ans = 21 % 2; /* Stores a 1 in ans */ If you divide the integer 21 by 2, you will get 10 with a remainder of 1. % discards the integer answer and keeps the remainder (the opposite of what the integer division operator would do). In Listing 7.1, you saw how the integer division operator worked. Listing 7.2 expands on that program by also showing modulus division and regular fractional division. There are two kinds of division operators, plus a modulus operator. Between these three operators, you can compute both answers and remainders. Input Listing 7.2. Computing divisional results. 1: // Filename: MOREDIV.CPP 2: // Computes two kinds of divisions and the modulus 3: #include <iostream.h> 4: void main() 5: { 6: int people, events, avgEv; 7: int leftOver; // Will hold modulus 8: float floatPeople; // Needed to force regular division 9: float exact; // Will hold exact average 10: 11: cout << "How many people will attend? "; 12: cin >> people; 13: cout << "How many events are scheduled? "; 14: cin >> events; 15: 16: // Compute the integer average number of people per event 17: avgEv = people / events; // The integer division ensures 18: // that the fractional part of 19: // the answer is discarded 20: cout << endl << "There will be an average of " << avgEv 21: << " people per event." << endl; 22: leftOver = people % events; 23: cout << "There will be " << leftOver 24: << " without an event at any one time." << endl; 25: floatPeople = people; // Converts the integer to a floating-point 26: exact = floatPeople / events; 27: cout << "The exact average number of people per event is " 28: << exact; 29: return; 30: } Output How many people will attend? 21 How many events are scheduled? 2 There will be an average of 10 people per event. There will be 1 without an event at any one time. The exact average number of people per event is 10.5. Analysis Line 7 defines an integer variable to hold the integer remainder calculated on line 22. Given the user's data-entry values shown in the output, one person will be left without an event. Line 8 defines a floating-point variable for the sole purpose of assigning the integer number of people entered in line 12 to line 8's floating-point variable, as done in line 25. After you learn about a Visual C++ feature named typecasting in Lesson 5, you won't need to define such an intermediate variable. When line 25 assigns the integer variable named people to the floating-point variable named floatPeople, the integer becomes a floating-point value. The conversion of the number of people to floating-point lets line 26 perform exact fractional division instead of integer division only. Another issue to beware of with division in C++ is what happens when you divide by zero. The answer to a mathematician is infinity; to a computer, the answer is a headache. You must never divide by zero, because this causes a severe error in your program. In later lessons, you will learn techniques to test the values in your program so that you can handle such an error gracefully. Order of Operators Visual C++ computes operators based on the order of operator precedence, found in Appendix C. definition Hierarchy is another name for operator precedence. Just like the math that your high school algebra teacher taught (you do remember high school algebra, don't you?), Visual C++ follows a certain order when evaluating expressions. Visual C++ doesn't compute all expressions from left to right. Instead, Visual C++ computes expressions based on the hierarchy in the order of operators table, shown in Appendix C. The higher the operators are in the table, the higher their precedence. Therefore, a unary minus operator is said to have higher precedence than the regular binary subtraction operator. The following assignment stores 10 in priority, not 18 as would be the case if Visual C++ calculated the expression from left to right: priority = 4 + 2 * 3; Appendix C's precedence table shows that multiplication has a higher precedence than addition; therefore, Visual C++ computes 2 * 3, getting 6, and then adds the 4 to the 6 to get the final answer of 10 to store in priority. You'll notice in the operator precedence table that multiplication and division both appear on the same level, as do addition and subtraction. When two operators of the same level appear in the same expression, as in another = 10 - 8 + 3; Visual C++ calculates the expression from left to right. 10 - 8 produces 2, and the 2 is added to the 3 to get 5. Parentheses override most operators because of their high level in the precedence table. If you were to put parentheses in the preceding expression, you could force Visual C++ to compute the expression differently. The expression another = 10 - (8 + 3); stores -1 in another because the 8 is added to the 3, producing 11, before the 11 is subtracted from 10, which gives you the -1 answer. Clarify your code as much as possible by using extra parentheses even if they're unnecessary. For example, parentheses aren't really needed in the expression another = (10 - 8) + 3; because Visual C++ calculates the subtraction first due to its position left of the addition in the expression. However, the parentheses show your intent and help you keep straight the order you meant to take place. Also, if you happen to misread the operator precedence table, the extra parentheses force the expression's evaluation to match your desired order, just in case Visual C++ wouldn't have calculated that order automatically. Perhaps a few more examples of combined operators will help clarify operator precedence even more. Study how Figure 7.1 illustrates the order of expression evaluation. Figure 7.1. Watch that order of precedence! definition To nest operations means to put one calculation inside another. Sometimes, you might need to nest parentheses inside one another. The innermost parentheses calculate first. Figure 7.2 shows how nested parentheses compute. Figure 7.2. Visual C++ calculates the innermost parentheses first. Be sure that your expressions have an equal number of opening and closing parentheses. These examples are great for learning Visual C++, but when you write your own Visual C++ programs, try to keep your expressions simple. Break a long expression into two or more expressions, even if doing so means defining an intermediate variable. The assignment netPay = grossPay - taxRate * grossPay + bonus; is easier to understand when you break it up like this: taxes = taxRate * grossPay; netPay = grossPay - taxes + bonus; Listing 7.3 contains a program that computes each of the three expressions illustrated in the previous two figures, proving beyond a shadow of a doubt how the order of precedence works. (You never doubted the figures, did you?) Visual C++ follows the order of operators when computing expressions. You can use parentheses to override many of the expressions' default order. Input Listing 7.3. Calculating long expressions in Visual C++. // Filename: EXPRESS.CPP // Computing expressions with C++ #include <iostream.h> void main() { int ans1, ans2, ans3; ans1 = 2 * 3 + 3 * 2; cout << "The first answer is " << ans1 << endl; ans2 = 20 + 20 / (5 + 5) % 2; cout << "The second answer is " << ans2 << endl; ans3 = ((2 + 3) + 6 * (3 + (4 - 2))) + 3; cout << "The third answer is " << ans3 << endl; return; } Output The first answer is 12 The second answer is 20 The third answer is 38 Analysis As shown here, Visual C++ computes mathematical results as described in this section and as dictated by the operator precedence table. In your regular Visual C++ programming, your programs will calculate using more variables than numeric literals, but you must understand how the calculating order works by practicing with simple integer literals as shown here. If you're ever unsure how Visual C++ will order an expression, use parentheses. If you're still unsure, write a simple program to test a sample expression using numeric literals so that you can practice with the expression. definition A debugger is a special tool that allows you to look at variables as your code executes step by step. If you are performing complicated calculations, there is another good reason for breaking up your calculation into several steps: It allows you to inspect the progress of the calculation with the Visual C++ integrated debugger. This useful tool lets you look inside the program as it works so that you can easily find errors that you cannot spot by just looking at the code. By running your program with the Debug | Go or Debug | Step Into command, you can step through your program a line at a time. The online help for the Visual Workbench explains how to do this under the section "Debugger: General Information." If you are having difficulty visualizing how Visual C++ does its math, now is the time to watch how it works with the debugger. Advanced Assignments Learn other ways to use the equal sign. The assignment operator has more power in Visual C++ than in other programming languages. The next two sections explain how the Visual C++ assignment operator combines with other operators to improve your power and decrease your programming effort. Multiple Assignments If you want to assign the same value to more than one expression, Visual C++ lets you string together multiple assignment statements. For example, if you wanted to put zero in several initial total variables, you could do this: total1 = 0; total2 = 0; total3 = 0; But multiple assignments like these make your work easier: total1 = total2 = total3 = 0; // Put 0 in three variables Look at Appendix C's operator table and you'll see a column labeled Associativity. This column tells you whether an expression works from right to left or left to right. The assignment operator associates from right to left. Figure 7.3 illustrates what a right-to-left associativity means. Figure 7.3. Operator associativity describes in which direction to operate. As Visual C++ assigns the zero to each variable on the right, that variable gets the zero and the entire expression becomes zero as well. That expression's zero is then available for the next variable to the left, and so on. Eventually, Visual C++ assigns the zero to total1 and the result of that expression is zero. There's nothing to do with that final zero, so Visual C++ discards it and continues execution at the next statement in the program. All expressions have values. The assignment statement not only assigns values, but it also creates a value while performing the assignment. Therefore, that value is available for subsequent assignment statements if there are any more assignments to be made to the left of that line. The value produced by the assignment lets you combine two statements such as monthAvg = dailyAvg * 30; yearAvg = 12 * monthAvg; into a single statement such as this: yearAvg = 12 * (monthAvg = dailyAvg * 30); Visual C++ first computes the monthly average and stores that average in monthAvg. The entire assignment expression in parentheses becomes a value that is then multiplied by 12 and assigned to yearAvg. Which of the two statement groups do you think is better? The second is (probably) more efficient, but too many Visual C++ programmers go overboard in trying to squeeze efficiency out of their programs. Although the first pair of statements isn't as efficient, it's much easier to read, maintain, and change later if needed. Although C++ provides many of these clever features, code is more understandable and maintainable if you avoid multiple assignments and mixing assignments in the middle of expressions. Associativity will come into play more as you learn about more powerful operators. Is a Rule Now Broken? Any astute reader (that's you, right?) will see right away that right-to-left associativity seems to violate a rule stated earlier in this unit. Earlier, you read that two or more operators in the same expression that appear on the same level in the operator precedence table compute from left to right. Well, now that you understand associativity, that "rule" can be set in stone with the following definition: "The associativity of operators determines the order in which they compute if two or more operators from the same precedence level appear in the same expression." All of the fundamental math operators (+, -, *, /, and %) have left-to-right associativity, so they do indeed compute from left to right when they appear on the same level in an expression. Stick to simple expressions and you will not need to worry about associativity. Compound Operators There are several operations that commonly put the same variable on both sides of the equal sign. Here are some examples: count = count + 1; // Add 1 to count salary = salary * bonusFactor; // Adjust the salary monthly = monthly + daily; // Add to daily sales When you see the same variable on both sides of an operator, the variable is being updated in some way. count is being increased by one, salary is being changed to reflect a bonus factor, and monthly is being updated with the current day's total sales (thus keeping a running monthly total). Such updating of variable values is so common that the designers of Visual C++ added several compound operators to Visual C++ that don't exist in other programming languages. If you want to update the value of a variable, why should you have to go to the trouble of repeating the variable name on both sides of the equal sign? (At least, that was the designers' thinking.) definition The compound operators are sometimes called compound assignment operators. Table 7.2 lists each of the compound operators and describes the equivalent assignment statements through examples. As you can see, the compound operators provide you with easier but equivalent updating capabilities. Table 7.2. The compound operators and their equivalent meanings. Compound Operator Example Equivalent Assignments += a += 100; a = a + 100; -= b -= 0.25; b = b - 0.25; *= c *= 13; c = c * 13; /= d /= 4; d = d / 4; %= e %= 2; e = e % 2;Be very careful when using the compound assignment operators! Before going any further, find the compound assignment operator precedence level in Appendix C's precedence table. You'll see that all the compound operators have lower precedence than the regular math operators. In other words, *= appears several levels down from the multiplication operator, *. Such precedence can cause you agony when you combine the compound assignment operators with other expressions that use the regular operators. For example, given the variable definitions int value = 5; int x = 3; how do you think you would change the following expression to use a compound subtraction operator? value = value - x + 2; // Be careful! At first, you might be tempted to rewrite such an expression as value -= x + 2; Doing so, however, does not yield the same results because the -= operator has much lower precedence than the plus sign and the regular minus sign. In the first assignment, the x is first subtracted from value, and then the 2 is added to that result before the final computed 4 is put in value. In the compound version, Visual C++ computes the -= only after adding the 2 and the x. Therefore, Visual C++ stores a 0 in value! The compound operator, due to its precedence, is actually equivalent to this statement: value = value - (x + 2); // Equivalent to value -= x + 2 As you're beginning to see, precedence can affect everything you compute in Visual C++. Earlier, this unit suggested that you enclose as much as you can in parentheses to clarify everything you do, even if normal precedence handles your calculation perfectly. The compound operators and their low precedence really make the use of ample parentheses vital. Instead of writing statements such as value -= x + 2; perhaps it would be safer to include parentheses so that both you and Visual C++ are on the same precedence wavelength: value -= (x + 2); So as not to confuse other programmers who might have to read your programs, it is safer not to use the compound operators in complicated expressions. Listing 7.4 contains a program that computes interest at the end of five compounding periods. Whenever you need to add to a total or update a variable in some way, the compound assignment operators give you lots of poweras long as you keep the operator precedence in mind. Input Listing 7.4. Computing interest for five periods. 1: // Filename: INTFIVE.CPP 2: // Compute five periods of interest 3: #include <iostream.h> 4: #include <iomanip.h> 5: void main() 6: { 7: float intRate; // Interest rate per period 8: float principal; // Loan amount 9: 10: cout << "Welcome to loan central!" << endl; // Title 11: cout << "------------------------" << endl << endl; 12: 13: cout << "How much was the loan for? "; 14: cin >> principal; 15: 16: cout << "What is the period interest rate (i.e., .03 for 3%)? "; 17: cin >> intRate; 18: 19: cout << "Here is the total owed after five periods" << endl; 20: cout << "(Assuming no payment is made)" << endl; 21: 22: principal *= (1 + intRate); // First period interest 23: principal *= (1 + intRate); 24: principal *= (1 + intRate); 25: principal *= (1 + intRate); 26: principal *= (1 + intRate); // Fifth period interest 27: 28: cout << setprecision(2); 29: cout.setf(ios::fixed); // Ensure two decimal places 30: cout.setf(ios::showpoint); 31: cout << "$" << principal 32: << " total amount owed after five periods." << endl; 33: return; 34: } Output Welcome to loan central! ------------------------ How much was the loan for? 1000.00 What is the period interest rate (i.e., .03 for 3%)? .10 Here is the total owed after five periods (Assuming no payment is made) $1610.51 total amount owed after five periods. Analysis The heart of this program lies in the computations on lines 22 through 26. Each line increases the loan principal by the interest rate for that period. If you were to need the original principal for a printed loan invoice or for an additional kind of calculation you add later, you would first have to save the original principal in another variable. Each compound assignment operator updates whatever value appears on the left side of the compound assignment, just as the regular assignment changes its lvalue. In Lesson 6, "Looping Back and Forth," you'll learn how to write programs using loops that eliminate some of the tedious repetition in Listing 7.4. If you are not confident with math, you might be concerned that computing is always about doing complicated calculations. In fact, the opposite is true. In even the most complicated programs, the majority of calculations are very simple. In commercial programming, the programmers job is not to work out the complicated formulafor example, mortgage repaymentsbut to translate the formula that an analyst will provide into computer code. Homework General Knowledge What's the difference between a unary operator and a binary operator? Suppose that you stored a -6 in the variable named amount. How could you then store the negative of amount in a variable called negAmount? What is meant by overloaded operator? How many kinds of division can / perform? What are they called? Which operator finds the remainder of integer division? What's another name for the remainder operator? Why does an assignment statement produce a value as well as an assignment? What is the associativity of the assignment operator? What is the associativity of the multiplication operator? What value would Visual C++ compute in the following expression? ((7 + 3) + 2) Why are the parentheses in question 10 not needed? What value would Visual C++ compute in the following expression? (1 + 2) * 3 / 4 What value would Visual C++ compute in the following expression? (1 + (10 - (2 + 2))) What value would Visual C++ compute in the following expression? 22 * 2 - 8 % (3 - 1) True or false: The unary plus sign is optional. True or false: The unary minus sign is optional. True or false: You can apply the unary minus sign to variables and expressions but not to integer literals. True or false: Binary operators work best for binary values. What's the Output? Here is a tricky multiline computational program! See if you can determine the output. // Filename: TRCKMATH.CPP // Computes several layers of expressions #include <iostream.h> void main() { int x; x = 2 + 5 * 2 - 1 % 2; x += 14; x -= 5; x *= 2 - 7; cout << "The value of x is " << x ; return;} Find the Bug What's wrong with the following assignment? netSales = sales -- adjustedSales; Write Code That. . . Write the assignment statement that performs the same math as the following formula: (9 - 5) a = ----- (3 * 12) Write the assignment statement that performs the same math as the following formula: y2 b = ---- (2 - q) Rewrite the following assignment statement so that it takes three separate assignments instead of one: a = (b = x * 12) * (c = 34 + w); Oops! You make so much writing Visual C++ programs that your taxes just went up eight percent! Write a statement that takes your current tax rate, stored in a variable named taxRate, and increases that rate by eight percent. (Hint: To increase a variable by eight percent, you can multiply the variable by (1 + .08).) Write the statement using a regular assignment and multiplication operator, and then write the statement with a compound assignment operator. Rewrite Listing 7.4 to print the principal after each period so that the user can see the loan amount building each period. Write a program to calculate the area of a circle whose radius is 2.4. The formula for a circle's area is area = PI * (radius2) Pi is approximately 3.14159. Hint: Pi is an excellent value to define as a constant using const. Rewrite question 26 so that the program asks the user for a radius and then computes the area of a circle that has the radius that the user specified. Extra Credit Write a program that computes the first five powers of 3 (31, 32, 33, 34, and 35). Print descriptions before each power. The first two lines of output would look like this: 3 raised to the power of 1 is 3 3 raised to the power of 2 is 9 William the Worker always works 52 hours a week. He earns $5.65 for the first 40 hours he works. He gets time and a half (1.5 times his regular hourly pay) for the first 10 hours over 40. He gets double time for all hours over 50. He is in the 32 percent tax bracket. Write a program with appropriate titles that prints William's gross pay, net pay, and taxes. |