Home Practices Page 3 - Basic Data Types and Calculations

# Try It Out: Integer Arithmetic in Action - Practices

This article looks at some of the basic data types that are built into C++. If you're learning how to use C++, you will want to keep reading, since you'll be using these data types in all of your programs. It is taken from chapter two of the book Beginning ANSI C++: The Complete Language, by Ivor Horton (Apress, 2004; ISBN: 1590592271).

Rating:  / 14
September 08, 2005

SEARCH DEV SHED

TOOLS YOU CAN USE

The following is a program to output the results of a miscellaneous collection of expressions involving integers to illustrate how the arithmetic operators work:// Program 2.1 - Calculating with integer constants
#include <iostream>             // For output to the screen
using std::cout;
using std::endl;

int main() {
cout << 10 + 20            << endl; // Output is 30
cout << 10 - 5             << endl; // Output is 5
cout << 10 - 20            << endl; // Output is -10

cout << 10 * 20            << endl; // Output is 200
cout << 10/3               << endl; // Output is 3
cout << 10 % 3             << endl; // Output is 1
cout << 10 % -3            << endl; // Output is 1
cout << -10 % 3            << endl; // Output is -1
cout << -10 % -3           << endl; // Output is -1

cout << 10 + 20/10 - 5     << endl; // Output is 7
cout << (10 + 20)/(10 - 5) << endl; // Output is 6
cout << 10 + 20/(10 - 5)   << endl; // Output is 14
cout << (10 + 20)/10 - 5   << endl; // Output is -2

cout << 4*5/3%4 + 7/3      << endl; // Output is 4
return 0;                           // End the program
}

The output from this example on my system is as follows:

30
5
-10
200
3
1
1
-1
-1
7
6
14
-2
4

It doesn’t look particularly elegant with that “ragged right” arrangement, does it? This is a consequence of the way that integers are output by default. Very shortly, you’ll come back to find out how you can make it look prettier. First, though, let’s look at the interesting parts of this example.

HOW IT WORKS

Each statement evaluates an arithmetic expression and outputs the result to the screen, followed by a newline character that moves the cursor to the beginning of the next line. All the arithmetic expressions here are constant expressions, because their values can be completely determined by the compiler before the program executes.

The first five statements are straightforward, and the reasons why they produce the results they do should be obvious to you:

cout << 10 + 20 << endl; // Output is  30
cout << 10 - 5 << endl;  // Output is   5
cout << 10 - 20 << endl; // Output is -10
cout << 10 * 20 << endl; // Output is 200
cout << 10/3 << endl;    // Output is   3

Because integer operations always produce integer results, the expression10/3in the last line results in3, as 3 divides into 10 a maximum of three times. The remainder, 1, that is left after dividing by 3 is discarded.

The next four lines show the modulus operator in action:

cout << 10 % 3    << endl;   // Output is 1
cout << 10 % -3   << endl;   // Output is  1
cout << -10 % 3   << endl;   // Output is -1
cout << -10 % -3  << endl;   // Output is -1

Here you’re producing the remainder after division for all possible combinations for the signs of the operands. The output corresponding to the first line where both operands are positive is the only one guaranteed to be the same when you run it on your system. The results of the other three lines may have a different sign.

The next four statements show the effects of using parentheses:

cout << 10 + 20/10 - 5      << endl;   // Output is  7
cout << (10 + 20)/(10 - 5)  << endl;   // Output is  6
cout << 10 + 20 /(10 - 5)   << endl;   // Output is 14
cout << (10 + 20)/10 - 5    << endl;   // Output is -2

The parentheses override the “natural order” of execution of the operators in the expressions. The expressions within parentheses are always evaluated first, starting with the innermost pair if they’re nested and working through to the outermost.

In an expression involving several different operators, the order in which the operators are executed is determined by giving some operators priority over others. The priority assigned to an operator is called its precedence.With the operators for integer arithmetic that you’ve seen, the operators*,/, and%form a group that takes priority over the operators+and-, which form another group. You would say that each of the operators*,/, and%has a higher precedence than+and-. Operators within a given group—+and–, for example—have equal precedence. The last output statement in the example illustrates how precedence determines the order in which the operators are executed:

cout << 4*5/3%4 + 7/3 << endl; // Output is 4

The+operator is of lower precedence than any of the others, so the addition will be performed last. This means that values for the two subexpressions,4*5/3%4and7/3, will be calculated first. The operators in the subexpression4*5/3%4are all of equal precedence, so the sequence in which these will be executed is determined by their associativity. The associativity of a group of operators can be either left or right. An operator that is left associative binds first to the operand on the left of the operator, so a sequence of such operators in an expression will be executed from left to right. Let’s illustrate this using the example.

In the expression4*5/3%4, each of the operators is left associative, which means that the left operand of each operator is whatever is to its left. Thus, the left operand for the multiplication operation is4, the left operand for the division operation is4*5, and the left operand for the modulus operation is4*5/3. The expression is therefore evaluated as((4*5)/3)%4, which, as I said, is left to right.

Although the associativity of the operators in an expression is involved in determining the sequence of execution of operators from the same group, it doesn’t say anything about the operands. For example, in the expression4*5/3%4+7/3, it isn’t defined whether the subexpression4*5/3%4is evaluated before7/3or vice versa. It could be either, depending on what your compiler decides. Your reaction to this might be “Who cares?” because it makes no difference to the result. Here, that’s true, but there are circumstances in which it can make a difference, and you’ll see some of them as you progress through this chapter.

Operator Precedence and Associativity

Nearly all operator groups are left associative in C++, so most expressions involving operators of equal precedence are evaluated from left to right. The only right associative operators are the unary operators, which I’ve already touched upon, and assignment operators, which you’ll meet later on.

You can put the precedence and associativity of the integer arithmetic operators into a little table that indicates the order of execution in an arithmetic expression, as shown in Table 2-2.

Table 2-2. The Precedence and Associativity of the Arithmetic Operators

Operators      Associativity
unary + -      Right
* / %          Left
+ -            Left

Each line in Table 2-2 is a group of operators of equal precedence. The groups are in sequence, with the highest precedence operators in the top line and the lowest precedence at the bottom. As it only contains three lines, this table is rather simplistic, but you’ll accumulate many more operators and add further lines to this table as you learn more about C++.

NOTE The C++ standard doesn’t define the precedence of the operators directly, but it can be determined from the syntax rules that are defined within the standard. In most instances it’s easier to work out how a given expression will execute from the operator precedence than from the syntax rules, so I’ll consider the precedence of each operator as I introduce it.

If you want to see the precedence table for all the operators in C++, you can find it in Appendix D.

 >>> More Practices Articles          >>> More By Apress Publishing