You have already seen numerous examples of how C# performs arithmetic calculations by evaluating arithmetic expressions, such as the following:
100 * Constants.MassOfElectron
((distance1 + distance2) / 2)
These examples give you a general idea of how a correct expression is put together and how it is evaluated. However, you can only create expressions that efficiently solve the computational problems of your particular program, if you know the different underlying building blocks of a C# expression and how these are combined to form valid expressions. The following sections are aimed at providing you with this knowledge.
Arithmetic operators (such as addition (+), subtraction (-), multiplication (*), and division (/)) combine with numbers called operands to form arithmetic expressions. Arithmetic expressions written in C# are fairly easy to interpret; they more or less follow the arithmetic rules we are used to from school.
The four basic arithmetic operators mentioned in the preceding section all need one operand on their left sides and one operand on their right sides. An arithmetic operator combining two operands to form an expression, such as
is called a binary operator. An operand can, in this context, take many forms. It can be a simple literal, such as 345.23, a variable, a constant representing a numerical value, or a numerical expression as in the following:
An operand can even be a method call. In this case, the method being called must have a return value. The following call to the Average method illustrates
These two method calls are both resolved before the addition operator is applied, and can then be regarded as the numbers 15.0 and 30.0, both of type double, the type of Average's return values as specified in its method header.
We can concisely express the five forms of an operand, by utilizing the syntax notation introduced in the previous chapter. This is done in Syntax Box 7.1.
Syntax Box 7.1 The OperandAn operand can be defined in five different ways: Operand ::= <Literal> ::= <Numerical_variable_identifier> ::= <Numerical_constant_identifier> ::= <Numerical_expression> ::= <Method_call> Note: The method called with <Method_call> must have a return value. |
Additionally, our perception of a numerical expression can be formalized as in Syntax Box 7.2.
Syntax Box 7.2 The Numerical ExpressionNumerical_expression ::= <Operand> <Binary_operator> <Operand> ::= <Numerical_expression> <Binary_operator> <Numerical_expression> Notes:
|
Because an operator surrounded by two operands forms a numerical expression, and an operand itself can be defined as a numerical expression, one way to define a numerical expression is as follows:
Numerical_expression::= <Numerical_expression> <Binary_operator> <Numerical_expression>
Consequently, any expression using more than two operands can always be divided into sub-expressions, each consisting of only two operands and one binary operator. After the result of each of these sub-expressions has been found, the results can be used to calculate the next level of sub-expressions. Consider the following expression:
4 * 5 + 40 * 10 20 * 40 / 10 + 70
At first, the expression seems to contain an overwhelming number of operators and operands (numbers), until we realize that it is composed of many sub-expressions. Figure 7.1 shows how we can apply our definition of a numerical expression to calculate the given expression.
In Figure 7.1, notice how multiplications are performed before additions, in accordance with the rules we learned in school. This fact is highlighted in Figure 7.2.
Consequently, when an operand (such as number 3 in Figure 7.2) can be processed by more than one operator (+ or *, in this case), C# uses precedence rules to decide which operator is applied first. These rules determine how expressions, such as the one shown in Figure 7.1, are divided into sub-expression.
Note
For simplicity, I have used literals in the numerical expressions of Figures 7.1 and 7.2. Obviously, I could have used a combination of any of the operand definitions given in Syntax Box 7.1. |
C# contains arithmetic operators other than the four binary operators previously mentioned. Each of them carries an exact precedence in relation to the others.
Table 7.1 gives an overview of the operators discussed in this chapter along with their precedence. A listing of the operators presented in this book can be found in Appendix B, "Operator Precedence."
Note
Table 7.1 shows several operators not yet presented; they have been included at this stage as a handy reference and overview when you read through the rest of the section. |
Please locate the four binary operators presented so far in Table 7.1. Observe that the multiplication (*) and division (/) operators both have a higher precedence than the addition (+) and subtraction (-) operators. This fits in nicely with our numerical expression examples and their results in Figures 7.1 and 7.2.
Precedence | Category | Symbol | Name | Associativity |
---|---|---|---|---|
1. | Primary | (<Numeric _expression>) | Parenthesis | |
Primary | ++ (postfix) (e.g. count++) | Increment Operator Postfix | Right-Left | |
Primary | -- (postfix) (e.g. count--) | Decrement Operator Postfix | Right-Left | |
2. | Unary | + | Unary plus | Right-Left |
Unary | - | Unary minus | Right-Left | |
Unary | ++ (prefix) (e.g. ++count) | Increment operator | Right-Left | |
Unary | -- (prefix) (e.g. --count) | Decrement operator | Right-Left | |
3. | Binary | * | Multiplication | Left-Right |
Binary | / | Division | Left-Right | |
Binary | % | Modulus | Left-Right | |
4. | Binary | + | Addition | Left-Right |
Binary | - | Subtraction | Left-Right | |
Notes: In the Precedence column, the lower the number, the higher the precedence. For an introduction to the Associativity concept please see the next section. |