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 ( |

// National Debt to the Penny decimal debt = -8279328785833.43M; |

^{[1]}As of March 8, 2006.

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.

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.

## Language Contrast: C++Operator-Only StatementsBinary operators in C# require an assignment or call; they always return a new result. Neither operand in a binary operator expression can be modified. In contrast, C++ will allow a single statement, such as |

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).

class Division { static void Main() { int numerator; int denominator; int quotient; int remainder; System.Console.Write("Enter the numerator: "); numerator = int.Parse(System.Console.ReadLine()); System.Console.Write("Enter the denominator: "); denominator = int.Parse(System.Console.ReadLine()); quotient = numerator / denominator; remainder = numerator % denominator; System.Console.WriteLine( "{0} / {1} = {2} with remainder {3}", numerator, denominator, quotient, remainder); } } |

Output 3.1 shows the results of Listing 3.3.

Enter the numerator: 23 Enter the denominator: 3 23 / 3 = 7 with remainder 2 |

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.

... error CS0201: Only assignment, call, increment, decrement, and new object expressions can be used as a statement |

## Beginner Topic: Associativity and Order of PrecedenceAs with mathematics, programming languages support the concept of associativity. Associativity refers to how operands are grouped and, therefore, the order in which operators are evaluated. Given a single operator that appears more than once in an expression, associative operators will produce the same result regardless of the order in which they are evaluated. Binary operators such as Associativity applies only when all the operators are the same. When different operators appear within a statement, the order of precedence for those operators dictates which operators are evaluated first. Order of precedence, for example, indicates that the multiplication operator be evaluated before the plus operator in the expression |

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.

classFortyTwo { static void Main() { short windSpeed = 42; System.Console.WriteLine( "The original Tacoma Bridge in Washington\nwas " + "brought down by a " + windSpeed + " mile/hour wind."); } } |

Output 3.3 shows the results of Listing 3.4.

The original Tacoma Bridge in Washington was brought down by a 42 mile/hour wind. |

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).

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`.

int n = '3' + '4'; char c = (char)n; System.Console.WriteLine(c); // Writes out g. |

Output 3.4 shows the results of Listing 3.5.

g |

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.

`int distance = 'f' 'c'; System.Console.WriteLine(distance);` |

Output 3.5 shows the results of Listing 3.6.

3 |

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`.

## Advanced Topic: Unexpected Inequality with FloatingPoint TypesThe inaccuracies of floats can be very disconcerting when comparing values for equality, since they can unexpectedly be unequal. Consider Listing 3.7. ## Listing 3.7. Unexpected Inequality Due to FloatingPoint Inaccuracies
Output 3.6 shows the results of Listing 3.7. ## Output 3.6.
The To avoid unexpected results caused by the inaccuracies of floatingpoint types, developers should avoid using equality conditionals with these types. Rather, equality evaluations should include a tolerance. One easy way to achieve this is to subtract one value (operand) from the other and then evaluate whether the result is less than the maximum tolerance. Even better is to use the decimal type in place of the float type. |

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.

float n=0f; // Displays: NaN System.Console.WriteLine(n / 0); |

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.

// Displays: -Infinity System.Console.WriteLine(-1f / 0); // Displays: Infinity System.Console.WriteLine(3.402823E+38f * 2f); |

-Infinity Infinity |

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.

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.

`int x; x = x + 2;` |

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.

`int x; x += 2;` |

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.

x -= 2; x /= 2; x *= 2; x %= 2; |

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.

spaceCount = spaceCount + 1; spaceCount += 1; spaceCount++; |

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.`

lines = lines - 1; lines -= 1; lines--; |

## Beginner Topic: A Decrement Example in a LoopThe increment and decrement operators are especially prevalent in loops, such as the ## Listing 3.15. Displaying Each Character's ASCII Value in Descending Order
Output 3.9 shows the results of Listing 3.15. ## Output 3.9.
The increment and decrement operators are used to count how many times to perform a particular operation. Notice also that in this example, the increment operator is used on a character ( |

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).

int count; int result; count = 0; result = count++; System.Console.WriteLine("result = {0} and count = {1}", result, count); |

result = 0 and count = 1 |

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.

int count; int result; count = 0; result = ++count; System.Console.WriteLine("result = {0} and count = {1}", result, count); |

Output 3.11 shows the results of Listing 3.17.

result = 1 and count = 1 |

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.

class IncrementExample { public static void Main() { int x; x = 1; // Display 1, 2. Console.WriteLine("{0}, {1}", x++, x++); // x now contains the value 3. // Display 4, 5. Console.WriteLine("{0}, {1}", ++x, ++x); // x now contains the value 5. // ... } } |

1, 2 4, 5 |

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.

## Advanced Topic: ThreadSafe Incrementing and DecrementingIn spite of the brevity of the increment and decrement operators, these operators are not atomic. A thread context switch can occur during the execution of the operator and can cause a race condition. Instead of using a |

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.

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.

flylib.com © 2008-2017.

If you may any questions please contact us: flylib@qtcs.net

If you may any questions please contact us: flylib@qtcs.net