Math Operators and Expressions

C and Fortran support mostly the same math operators, except that Fortran supports exponentiation, which is done in C using the pow() library function.

Precedence and associativity in C and Fortran are the same as in algebra. Grouping () has the highest precedence, followed by negation (unary minus), then exponentiation, then multiplication and division, then addition and subtraction.

The C math operators are listed in Table 17.7, “Basic Math Operators in C”. C also has a number of additional operators for bitwise operations, since it is often used for systems programming, cryptography, etc. They are shown in Table 17.8, “Bitwise Operators in C”.

Table 17.7. Basic Math Operators in C

OperatorOperationPrecedenceAssociativity / Order of Operation
()Grouping1 (highest)Inside to outside
-Negation2Right to left
++Increment2Nearest to farthest
--Decrement2Nearest to farthest
*Multiplication3Left to right
/Division3Left to right
%Mod (remainder)3Left to right
+Addition4Left to right
-Subtraction4Left to right
[operator]= (=, +=, -=, etc.)Assignment6Right to left

Table 17.8. Bitwise Operators in C

OperatorOperationPrecedenceAssociativity / Order of Operation
~Complement (invert all bits)2 (same as unary -)Left to right
<<Shift left5 (below + and -)Left to right
>>Shift right5 (below + and -)Left to right
&Bitwise AND6Left to right
^Bitwise XOR6Left to right
|Bitwise OR6Left to right
[operator]= (=, +=, -=, etc.)Assignment7Right to left

The C shift operators can often be used in place of integer multiplication and division to greatly improve program speed. When we shift the digits of a decimal number one place to the left, it has the effect of multiplying the value by 10. Likewise, shifting to the right divides by 10.

Caution

Right-shifting an odd negative number will produce a result that is off by 1 from the mathematical definition of integer division. Programs that might do this must manually adjust.

The same principal applies to any other number base, including base 2, which is used to store integers internally. This works with both unsigned binary and 2's complement values. Hence, the following two statements are the same:

c = c * 8;
c = c << 3;   // Multiplies by 2, three times
        

The second statement may be significantly faster. A shift of any number of bits can occur within a single clock cycle in most modern CPUs, while multiplication may require many clock cycles. Some optimizers are smart enough to recognize which of your multiplications can be done with a shift and will generate a shift instruction automatically. However, it's best not to rely on such features. Using a shift instruction explicitly will ensure that your code is optimal no matter where it is compiled and executed.

The C increment and decrement operators are a convenient way to add 1 to or subtract 1 from a variable. The following two statements have the same effect:

++c;
c++;
        

Like all C operators, increment and decrement operators can also be used within expressions, though. This often allows us to eliminate a separate statement for incrementing a counter variable, which improves code density.

When used this way, the value of the expression will depend on whether the ++ or -- comes before (pre-increment, pre-decrement) or after (post-increment, post-decrement) the variable. If it comes before, then the increment occurs before the value of the variable is used in the expression, and vice versa.

a = 1;
b = 5 + ++a;    // Pre-increment: b is now 7 and a is 2
        
a = 1;
b = 5 + a++;    // Post-increment: b is now 6 and a is 2
        

C also allows us to combine any binary (two-operand) operator with '=' to save typing in common situations. The following two statements are equivalent:

c = c + 7;
c += 7;
        

This feature can also be used inside an expression, but must be parenthesized:

a = 1;
b = 5 + (a += 10);  // b is now 16 and a is 11
        

Fortran supports most common algebraic operators, including exponentiation:

Table 17.9. Basic Math Operators in Fortran

OperatorOperationPrecedenceOrder of Operation
()grouping1 (highest)inside to outside
**exponentiation3right to left
-negation3right to left
*multiplication4left to right
/division4left to right
+addition5left to right
-subtraction5left to right

Example 17.1. Precedence and Order of Evaluation

        a + b + c equals (a + b) + c equals a + (b + c)
        a - b - c equals (a - b) - c does not equal a - (b - c)
        a ** b ** c equals a ** (b ** c) does not equal (a ** b) ** c 
        

Unary minus is the same as multiplication by -1 or subtracting from 0, so -x equals -1 * x equals 0 - x.

Math operators are sensitive to the data types of the operands and may produce difference results for different types, i.e. they are polymorphic.

Recall from grade school that integer division and real division are not the same. Integer division results in an integer quotient and a remainder, while real division results in a different quotient and no remainder. ( The real quotient is the integer quotient + remainder / divisor. )

The C and Fortran divide operator (/) performs integer division if both operands are integers, and floating point division if either operand is floating point. Pay attention to the types of the operands when dividing, whether they are variables or constants.

int     a = 5, b = 10;
double  x, y, z = 10;
x = a / 2;      // a and 2 are both integers, x = 2.0, remainder discarded
y = a / 2.0;    // 2.0 is floating point, y = 2.5
x = a / b;      // a and b are both integers, x = 0.0, remainder discarded
x = a / z;      // z is floating point, x = 0.5
        

Caution

When using the division operator (/), care must be taken not to divide by zero.

Likewise, the exponentiation operator (**) cannot be used with negative bases and certain fractional exponents, unless working with complex numbers. For example, (-1) ** (0.5) does not exist in the real numbers, and hence will cause an error in Fortran.

Practice

Note

Be sure to thoroughly review the instructions in Section 2, “Practice Problem Instructions” before doing the practice problems below.
  1. What are the precedence and associativity rules for basic math operators in C and Fortran, compared with algebra?

  2. How does bit shifting relate to multiplication and division?

  3. Show a C statement that subtracts 1 from the variable x and adds the old value of x to y.

  4. What is the value of y after each of the following statements?

        int     a = 1, b = 2, c = 3;
        double  x = 4.0, y;
        
        y = a / b;
        y = c / b;
        y = c / x;