C# Tutorial 9 | Numeric Types Part 2 Bitwise Operators
Numeric Types Part 2. Bitwise Operators
Bitwise Operations
Bitwise operations are operations that operate on the individual bits in a binary representation of a number.
Complement Bitwise Operator
The complement bitwise operator will take the complement of the bits in representation, in other words, all zeros will be changed to ones and all ones will be changed to zeros.
Complement Bitwise Operator
And Bitwise Operator
The and bitwise operator will check to see if a bit exists in matching positions and if they do, this will be carried into the resulting value.
AND bitwise
Or Bitwise Operator
The bitwise OR operator has the same principle as the bitwise And operator apart from the check is to see if either literal have a 1.
For example
OR bitwise
Exclusive or Bitwise Operator
The exclusive Or bitwise operator will check to see if either the same position in each literal is 1 but NOT both e.g. 1 ^ 1 == False but 1 ^ 0 or 0 ^ 1 == True.
Exclusive OR operation
Shift Left Bitwise Operator
The shift left bitwise operator will take the current bits in a literal and move them a specified number of positions to the left, generally making the number larger, unless you move a 1 into the signed (negative) position.
int a = 0b0000_1111; int b = a << 2;
Console.WriteLine(b); //Outputs 60 (00111100)
Shift Right Bitwise Operator
The shift left bitwise operator will take the current bits in a literal and move them a specified number of positions to the right, generally making the number smaller.
int a = 0b0011_1100; int b = a >> 2;
Console.WriteLine(b); //Outputs 15 (00001111)
8-Bit and 16-Bit Integral Types
As mentioned in a previous section, byte/sbyte and short/ushort integral types lack their own arithmetic operators, however, if we try to perform these operations on 8 and 16-bit types we can see normal behaviour.
To achieve this C# implicitly converts these to be larger types when it is required. The result of the implicit conversion will be of the larger data type, therefore in order to receive the original, smaller data type, you would need an explicit cast back to the original type.
For example:
byte a = 2; byte b = 4; byte c = (byte) (a + b);
Console.WriteLine(c); //Outputs 6
Special Values for the Float and Double Types
The float and double types have values that represent special constants such as positive and negative infinity, as well as NaN (Not a Number).
Epsilon represents the smallest positive Double value that is significant in a numeric operation and can be accessed in the following manner.
Console.WriteLine(Double.Epsilon); NaN represents a value that is not a number and can be accessed in the following manner:
Console.WriteLine(Double.NaN); The negative infinity constant is the equivalent to dividing a negative number by 0.
Console.WriteLine(Double.NegativeInfinity); The positive infinity constant is the equivalent to dividing a positive number by 0.
Console.WriteLine(Double.PositiveInfinity );
Double vs. Decimal Type
Despite both being floating-type values, double and decimal have internal differences which set them apart.
The decimal type was created with dealing with money and other financial functions, this is due to it having base-10 as its internal representation.
Base-10 is important for financial calculations as it has a high precision for numbers that can be represented in base 10 where base 2 might not always be able to do this. For more information on this topic please visit the C# documentation: https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/floating-point-numeric-types
However, the decimal type is far slower to use as it isn’t native to the processor, has a much smaller range, as well as not having the special values such as Nan, +0, -0, positive infinity, negative infinity etc.
For this reason, it is recommended that double be used for scientific applications.
Testing for Equality on Numeric Types
The two basic operators that text for equality are ” == ” (equals) and ” != ” (does not equal). These two operators are valid for testing value types such as ints, longs, bytes etc. They can be used in the following manner:
int firstInt = 10; int secondInt = 20; int thirdInt = 30 - 10;
Console.WriteLine(firstInt == secondInt); //False Console.WriteLine(firstInt == thirdInt); //True
Reference Type Equality
Testing for equality between reference types with these two operators is not valid. The check is made on the reference rather than the value, so if you were to define two objects from the same class with the same value then the ” == ” operator would still return false. We will look into the comparison of reference types in a later entry.
Logical Operators
The logical operators || (OR) and && (AND) check to see if the boolean representation of values matches logical patters. For example:
Console.WriteLine(true || true); //True Console.WriteLine(false || false); //False Console.WriteLine(true || false); //True Console.WriteLine(false || true); //True
Console.WriteLine(true && true); //True Console.WriteLine(false && false); //False Console.WriteLine(true && false); //False Console.WriteLine(false && true); //False The not operator (!) can be used to negate the outcome of a logical comparison, for example, with the above example.
Console.WriteLine(!(true || true)); //False Console.WriteLine(!(false || false)); //True Console.WriteLine(!(true || false)); //False Console.WriteLine(!(false || true)); //False
Console.WriteLine(!(true && true)); //False Console.WriteLine(!(false && false)); //True Console.WriteLine(!(true && false)); //True Console.WriteLine(!(false && true)); //True THE TERNARY OPERATOR The ternary operator is a statement which will have two corresponding outcomes depending on if a statement equates to true or false.
The true result is placed ahead of the false result and is separated by a colon.
Console.WriteLine(true ? "This was true" : "This was false"); Console.WriteLine(false ? "This was true" : "This was false");