Operators

Posted: Saturday, April 4
Last modified: Saturday, April 4


As previously mentioned an operator is a basic operation that gets applied to modify data (operands). Operators for the most part are executed within a single clock cycle on CPU of a computer. Well, at least with Integers. Floats are more time costly. One reason for this is due to floating point values having special bit arrangements. Chars for the most part are treated like ints, especially in regards to operators and performance.

There are a several different types of operators; logical, bitwise, arithmetic, assigning and everything outside of that list would be considered miscellaneous. I'll mainly be covering logical, arithmetic and bitwise in this post.

The language you are going to use might have a slight tweek to the syntax, but typically the syntax will look as follows:
//in logic syntax, value is a boolean, bitwise and arithmetic the value 
//would be of some other data type.
value = operand operator operand
Given the previous example, we can dig a little deeper on assigning operators. For the purpose of this post, that equals sign ("=") is an assigning operator. This is not as complex as the other operators, but syntactically, you assign values to a given variable. It is also important to note, most operators can be coupled/used with an assignment operator. I'll give some basic examples in the arithmetic section.

Logical

Now, let us move onto the logical operators. These are used in boolean expressions -- anything that evaluates down to true or false. These include AND, OR, XOR and the NEGATE operator. A boolean expression is a statement in code that evaluates (simplified down to) true or false. The logical operators syntactically (with exception of the NEGATE) require a boolean (or boolean expression) on both sides.
boolean operand1 = true;
boolean operand2 = false;

//AND is typically represented as &&
boolean bool_expr1 = operand1 && operand2; //evaluates to (true AND false), false
boolean bool_expr2 = true && operand1; //evaluates to (true AND true), true
boolean bool_expr3 = false && operand2; //evaluates to (false AND false), false

//OR is typically represented as ||
boolean bool_expr4 = operand1 || operand2; //evaluates to (true OR false), true
boolean bool_expr5 = true || operand1; //evaluates to (true OR false), true
boolean bool_expr6 = false || operand2; //evaluates to (false OR false), false

//XOR is typically represented as ^ or sometimes ~
boolean bool_expr7 = operand1 ^ operand2; //evaluates to (true XOR false), true
boolean bool_expr8 = operand1 ^ true; //evaluates to (true XOR true), false
boolean bool_expr9 = false ^ operand2; //evaluates to (false XOR false), false

//NEGATE is special. Typically it is represented as !
//NEGATE occurs in front of a single boolean_expression and inverses it
boolean bool_expr10 = !operand1; //evaluates to NEGATE true, false
boolean bool_expr11 = !operand2; //evaluates to NEGATE false, true
boolean bool_expr12 = !operand1 || operand2; //evaluates to (NEGATE true OR false), false
boolean bool_exprBONUS = !(operand1 && operand2); //evaluates to true
//can you figure out why exprBONUS evaluates to true?
logical operators and boolean expressions are almost (but not always) used in If-Else-Then type statements and looping conditions.

Arithmetic

Hopefully the logic operators make sense to you by this point. The arithmetic operators are all math related. Most of the time how you would enter the values into a calculator are exactly how you would do it in code! For example:
int a = 2 + 5; //addition, a is assigned tha value 7
int b = 2 - 5; //subtraction, b is assigned the balue -3
int c = 2 * 5; //multiplication, c is assigned the value 10
int d = 2 / 5; //division, the quotient, d is assigned the value 0
int e = 2 % 5; //mod, the remainder of the quotient, is assigned the value 2
The above are fairly basic. With the exception of maybe modulus, I would assume they all behaved as one would expect. However there are also some other arithmetic operators, which are heavily used in programming. These include Increment (typically "++") and Decrement (typically "--"). Increment and Decrement are different from the other arithmetic operators in that they modify the target operand.
int a = 10;
int b = 10;
a++; //post increment, will increase by one after the line of code is executed.
++a; //pre increment, will increase by one before the line of code is executed.
b--; //post decrement, will decrease by one after the line of code is executed.
--b; //pre decrement, will decrease by one before a line of code is executed.
Incrementing and decrementing values is perhaps most useful in loops. This can be observed when looking through all the values in an array. That however, is beyond the topic of this post.

Integer Division

A common trip up is the division and the mod operators, specifically with integer math. In integer math you can only ever have whole numbers. This means that in division you are going to truncate any and all remaining decimal places or fractions of values. So for the purpose of clarification:
int a = 0 / 2; //a is assigned 0
int b = 1 / 2; //b is assigned 0 
int c = 2 / 2; //c is assigned 1
int d = 3 / 2; //d is assigned 1
int e = 4 / 2; //e is assigned 2
int f = 5 / 2; //f is assigned 2	

Floating Point (expected) Division

However, some of the arithmetic operators produce different results based on the type of operand. Integer math is performed on integers, Floating points and Double precision floating points are capable of holding fractions of values. So depending on the language, the same assignments to floats with float values would go as follows:
float a = 0.0 / 2.0; //a is assigned 0
float b = 1.0 / 2.0; //b is assigned 0.5 
float c = 2.0 / 2.0; //c is assigned 1.0
float d = 3.0 / 2.0; //d is assigned 1.5
float e = 4.0 / 2.0; //e is assigned 2.0
float f = 5.0 / 2.0; //f is assigned 2.5	

Bitwise

Bitwise operators are my personal favorite. They deal with binary manipulation. These operations are fast, extremely fast. Below are some common bitwise operators:
//Bitwise AND, AND's the bits together
// 0b 1111 1111 = 255
// 0b 1000 0000 = 128
// AND'd Together:
// 0b 1000 0000 = 128
int a = 255 & 128; //a is assigned 128

//Bitwise OR, OR's the bits together
// 0b 1000 0000 = 128
// 0b 0111 1111 = 127
// OR'd Together:
// 0b 1111 1111 = 255
int b = 128 | 127; //b is assigned 255

//bitwise XOR, XOR's the bits together
// 0b 1111 1111 = 255
// 0b 1010 1010 = 170
// XOR'd Together:
// 0b 0101 0101 = 85
int c = 255 ^ 170; //c is assigned 85

//bitwise SHIFT RIGHT
// 0b 1111 1111 = 255
// RIGHT SHIFT 1 BIT
// 0b 0111 1111 = 127
int d = 255 >> 1; //c is assigned 127

//bitwise SHIFT LEFT
// 0b 0111 1111 = 127
// LEFT SHIFT 1 BIT
// 0b 1111 1110 = 254
int e = 127 << 1; //d is assigned 254
Bitwise operators are essential to low level programming and key to optimal performance. They usually only take 1 cpu cycle. I only listed two means of shifting. There are special shifting ops that allow one to relocate the bits being shifted, a loop-around of sorts. Also, like the arithmatic bitwise operators can be followed by an assignment operator. However, check with your languages syntax before assuming the following would work as is:
int a = 255;
a &= 128; //a is assigned 128

int b = 128;
b |= 127; //b is assigned 255

int c = 255;
c ^= 170; //c is assigned 85
As a final point, shifting in my humble opinion is the key to fast computation. When done correctly, shifting allows for the multiplication and division by powers of 2. If things are done carefully, there exists a means of computation where more expensive multiplication and division can be removed from the equation.
Developed by Arthur Weborg

r2msoe@gmail.com