Now that you have been introduced to the predefined data types (refer to Chapter 2), you can begin to learn more about how to use these data types in combination with operators in order to perform calculations. For example, you can make calculations on variables that you have declared.
Operators are generally broken down into three categories: unary, binary, and ternary, corresponding to the number of operands 1, 2, and 3, respectively. This section covers some of the most basic unary and binary operators. Ternary operators appear later in the chapter.
Plus and Minus Unary Operators (+, )
Sometimes you may want to change the sign of a numerical variable. In these cases, the unary minus operator () comes in handy. For example, Listing 3.2 changes the total current U.S. debt to a negative value to indicate that it is an amount owed.
Listing 3.2. Specifying Negative Values 
Using the minus operator is equivalent to multiplying a number by -1.
The unary plus operator (+) has no effect on a value. It is a superfluous addition to the C# language and was included for the sake of symmetry.
Arithmetic Binary Operators (+, , *, /, %)
Binary operators require two operands in order to process an equation: a left-hand side operand and a righthand side operand. Binary operators also require that the code assign the resulting value to avoid losing the resulting value.
The subtraction example in Listing 3.3 is an example of a binary operatormore specifically, an arithmetic binary operator. The other arithmetic binary operators are addition (+), division (/), multiplication (*), and remainder (%; sometimes called the mod operator).
Listing 3.3. Using Binary Operators
Output 3.1 shows the results of Listing 3.3.
Note the order of associativity when using binary operators. The binary operator order is from left to right. In contrast, the assignment operator order is from right to left. On its own, however, associativity does not specify whether the division will occur before or after the assignment. The order of precedence defines this. The precedence for the operators used so far is as follows:
1) *, /, and %, 2) + and , and 3) =
Therefore, you can assume that the statement behaves as expected, with the division and remainder operators occurring before the assignment.
If you forget to assign the result of one of these binary operators, you will receive the compile error shown in Output 3.2.
Using the Plus Operator with Strings
Operators can also work with types that are not numeric. For example, it is possible to use the plus operator to concatenate two or more strings, as shown in Listing 3.4.
Listing 3.4. Using Binary Operators with NonNumeric Types
Output 3.3 shows the results of Listing 3.4.
Because sentence structure varies among languages in different cultures, developers should be careful not to use the plus operator with strings that require localization. Composite formatting is preferred (refer to Chapter 1).
Using Characters in Arithmetic Operations
When introducing the char type in the last chapter, I mentioned that even though it stores characters and not numbers, the char type is an integer type. It can participate in arithmetic operations with other integer types. However, interpretation of the value of the char type is not based on the character stored within it, but rather, on its underlying value. The digit 3, for example, contains a Unicode value of 0x33 (hexadecimal), which in base 10 is 51. The digit 4, on the other hand, contains a Unicode value of 0x34, or 52 in base 10. Adding 3 and 4 in Listing 3.5 results in a hexadecimal value of 0x167, or 103 in base 10, which is equivalent to the letter g.
Listing 3.5. Using the Plus Operator with the char Data Type
Output 3.4 shows the results of Listing 3.5.
You can use this trait of character types to determine how far two characters are from one another. For example, the letter f is three characters away from the letter c. You can determine this value by subtracting the letter c from the letter f, as Listing 3.6 demonstrates.
Listing 3.6. Determining the Character Difference between Two Characters
Output 3.5 shows the results of Listing 3.6.
Special FloatingPoint Characteristics
The floatingpoint types, float and double, have some special characteristics, such as the way they handle precision. This section looks at some specific examples, as well as some unique floatingpoint type characteristics.
A float, with seven digits of precision, can hold the value 1,234,567 and the value 0.1234567. However, if you add these two floats together, the result will be rounded to 1234567, because the decimal portion of the number is past the seven significant digits that a float can hold. This type of rounding can become significant, especially with repeated calculations or checks for equality (see the upcoming Expert Topic, Unexpected Inequality with FloatingPoint Types).
Note that inaccuracies can occur with a simple assignment, such as double number = 4.2F. Since the double can hold a more accurate value than the float can store, the C# compiler will actually evaluate this expression to double number = 4.1999998092651367;. 4.1999998092651367 is 4.2 as a float, but not quite 4.2 when represented as a double.
You should be aware of some additional unique floatingpoint characteristics as well. For instance, you would expect that dividing an integer by zero would result in an error, and it does with precision data types such as int and decimal. float and double, however, allow for certain special values. Consider Listing 3.8, and its resulting output, Output 3.7.
Listing 3.8. Dividing a Float by Zero, Displaying NaN
In mathematics, certain mathematical operations are undefined. In C#, the result of dividing 0F by the value 0 results in "Not a Number," and all attempts to print the output of such a number will result in NaN. Similarly, taking the square root of a negative number (System.Math.Sqrt(-1)) will result in NaN.
A floatingpoint number could overflow its bounds as well. For example, the upper bound of a float type is 3.4E38. Should the number overflow that bound, the result would be stored as "positive infinity" and the output of printing the number would be Infinity. Similarly, the lower bound of a float type is 3.4E38, and assigning a value below that bound would result in "negative infinity," which would be represented by the string -Infinity. Listing 3.9 produces negative and positive infinity, respectively, and Output 3.8 shows the results.
Listing 3.9. Overflowing the Bounds of a float
Further examination of the floatingpoint number reveals that it can contain a value very close to zero, without actually containing zero. If the value exceeds the threshold for the float or double type, then the value of the number can be represented as "negative zero" or "positive zero," depending on whether the number is negative or positive, and is represented in output as 0 or 0.
The parenthesis operator allows you to group operands and operators so that they are evaluated together. This is important because it provides a means of overriding the default order of precedence. For example, the following two expressions evaluate to something completely different:
(60 / 10) * 2 60 / (10 * 2)
The first expression is equal to 12; the second expression is equal to 3. In both cases, the parentheses affect the final value of the expression.
Sometimes the parenthesis operator does not actually change the result, because the orderofprecedence rules apply appropriately. However, it is often still a good practice to use parentheses to make the code more readable. This expression, for example:
fahrenheit = (celsius * 9 / 5) + 32;
is easier to interpret confidently at a glance than this one is:
fahrenheit = celsius * 9 / 5 + 32;
Developers should use parentheses to make code more readable, disambiguating expressions explicitly instead of relying on operator precedence.
Assignment Operators (+=, =, *=, /=, %=)
Chapter 1 discussed the simple assignment operator, which places the value of the righthand side of the operator into the variable on the lefthand side. Other assignment operators combine common binary operator calculations with the assignment operator. Take Listing 3.10, for example.
Listing 3.10. Common Increment Calculation
In this assignment, you first calculate the value of x + 2 and then you assign the calculated value back to x. Since this type of operation is relatively frequent, an assignment operator exists to handle both the calculation and the assignment with one operator. The += operator increments the variable on the lefthand side of the operator with the value on the righthand side of the operator, as shown in Listing 3.11.
Listing 3.11. Using the += Operator
This code, therefore, is equivalent to Listing 3.10.
Numerous other combination assignment operators exist to provide similar functionality. You can use the assignment operator in conjunction with not only addition, but also subtraction, multiplication, division, and the remainder operators, as Listing 3.12 demonstrates.
Listing 3.12. Other Assignment Operator Examples
Increment and Decrement Operators (++, )
C# includes special operators for incrementing and decrementing counters. The increment operator, ++, increments a variable by one each time it is used. In other words, each code line shown in Listing 3.13 is equivalent.
Listing 3.13. Increment Operator
Similarly, you can also decrement a variable by one using the decrement operator, . Therefore, all the code lines shown in Listing 3.14 are also equivalent.
Listing 3.14. Decrement Operator
Just as with the assignment operator, the increment operator also returns a value. In other words, it is possible to use the assignment operator simultaneously with the increment or decrement operator (see Listing 3.16 and Output 3.10).
Listing 3.16. Using the PostDecrement Operator
You might be surprised that count is assigned to result before it is incremented. This is why result ends up with a value of 0 even though count ends up with a value of 1.
If you want the increment or decrement operator to take precedence over the assignment operator and to execute before assigning the value, you need to place the operator before the variable being incremented, as shown in Listing 3.17.
Listing 3.17. Using the PreIncrement Operator
Output 3.11 shows the results of Listing 3.17.
Where you place the increment or decrement operator determines the order of operations, which affects how the code functions. If the increment or decrement operator appears before the operand, then the value returned will be the new value. If x is 1, then ++x will return 2. However, if a postfix operator is used, x++, the value returned by the expression will still be 1. Regardless of whether the operator is postfix or prefix, the resulting value of x will be different. The difference between prefix and postfix behavior appears in Listing 3.18. The resulting output is shown in Output 3.12.
Listing 3.18. Comparing the Prefix and Postfix Increment Operators
As Listing 3.18 demonstrates, where the increment and decrement operators appear relative to the operand can affect the result returned from the operator. Preincrement/decrement operators return the result after incrementing/decrementing the operand. Postincrement/decrement operators return the result before changing the operand. Developers should use caution when embedding these operators in the middle of a statement. When in doubt as to what will happen, use these operators independently, placing them within their own statements. This way, the code is also more readable and there is no mistaking the intention.
Constant Expressions (const)
The previous chapter discussed literal values, or values embedded directly into the code. It is possible to combine multiple literal values in a constant expression using operators. By definition, a constant expression is one that the C# compiler can evaluate at compile time (instead of calculating it when the program runs). For example, the number of seconds in a day can be assigned as a constant expression whose result can then be used in other expressions.
The const keyword in Listing 3.19 locks the value at compile time. Any attempt to modify the value later in the code results in a compile error.
Listing 3.19. Declaring a Constant
Note that even the value assigned to secondsPerWeek is a constant expression, because the operands in the expression are also constants, so the compiler can determine the result.