SOFTWARE DEVELOPMENT 1 Operators 2018W (Institute of Pervasive Computing, JKU Linz)
OPERATORS Operators are required to form expressions. Depending on the number of operands they take, they are called: unary (1), binary (2) and ternary (3) operators Operators always take specific types of input operands and produce a specific type of output data type. E.g. the multiplication operator in the expression 5 * 2 takes two int literals and produces an int result. Unless the operators have diverging priorities (e.g. * before +), evaluation is performed from left to right: c = 5 * a + 7 * (3 - b); 1 2 5 4 3 Types of operators: arithmetic, comparative, assignment, logical Software Development 1 // 2018W // 2
ARITHMETIC OPERATORS (+, -, *, /, %) Operations: addition (+), subtraction (-), multiplication (*), division (/) and modulo-division (%) Arithmetic operators are binary infix operators: require 2 operands binary positioned between 2 operands infix Modulo-division means division remainder: e.g. 11 / 3 = 3, remainder 2, then 11 % 3 produces 2 Arithmetic operators can be applied to variables and expressions of the types char, byte, int, long, float and double. The 2 operands do not need to be of the same type. Divisions by zero are allowed for the numeric floating-point types float and double, in which case the result is the special value infinity. For any integer data type a division by zero will raise a runtime error. Software Development 1 // 2018W // 3
POSTFIX- AND PREFIX INCREMENT AND DECREMENT Contrary to the other arithmetic operators, increment and decrement operators are unary, meaning, they only have a single operand. ++ is the increment and -- the decrement operator They require a variable as operand (literals or expressions are not allowed) and increase, respectively decrease, the variable by 1 Depending on the position of the operator, different values are returned: Prefix (e.g. ++a) first increases/decreases the variable value, then returns the new value Postfix (e.g. a++) increases/decreases the variable value, but returns the value from before the operation Since these operators change variable values as a side effect, try to avoid complex expressions with them, e.g. x = a * b++ + ++b; (nightmare!) Software Development 1 // 2018W // 4
POSTFIX- AND PREFIX INCREMENT AND DECREMENT Preincrement int a = 5; int b = ++a; is identical to a = a + 1; b = a; Result: a = 6 b = 6 Postincrement int a = 5; int b = a++; is identical to b = a; a = a + 1; Result: a = 6 b = 5 Software Development 1 // 2018W // 5
ARITHMETIC OPERATORS :: EXAMPLE int temperature = 20, delta = 5; // decrease temperature by 10, then multiply with delta. // aside from assigning the result to temperature, delta // is increased by one temperature = (temperature - 10) * delta++; // result: temperature is 50, delta is 6 // postfix and prefix decrement: int gamma = --delta - delta--; // first evaluate --delta: result is 5 and delta = 5 // then evaluate delta--: result is 5 and delta = 4 // lastly evaluate --delta - delta--, meaning: 5-5 // result: gamma is 0, delta is 4 gamma = delta++ - ++delta; // result: gamma is -2, delta is 6 // modulo-division: get remainder of delta / 6 delta = delta % 6; // result: delta is 0 SWE1.02 / ExpArithmetic.java Software Development 1 // 2018W // 6
ARITHMETIC OPERATORS :: OVERVIEW Operator Name Meaning + Positive Sign +a is identical to a - Negative Sign -a reverses the sign + Sum a + b computes the sum of a and b - Difference a b computes the difference of a and b * Product a * b computes the product of a and b / Division a / b computes the quotient of a and b % Remainder a % b computes the remainder of a / b ++ Preincrement ++a returns a+1 and increases a by 1 ++ Postincrement a++ returns a and increases a by 1 -- Predecrement --a returns a 1 and decreases a by 1 -- Postdecrement a-- returns a and decreases a by 1 In most languages the modulo operator (%) can only be applied to integer numbers, in Java floating point numbers also valid. Software Development 1 // 2018W // 7
EQUALITY AND RELATIONAL OPERATORS Equality and relational operators compare two expressions: binary infix operators resulting data type is always boolean Operations: Equal to (==), Not equal to (!=) Greater than (>), Less than (<) Greater than or equal to (>=), Less than or equal to (<=) Example: int a = 3, b = 4, c = 7; boolean check1 = a + b == c; // check1 is true boolean check2 = a > b; // check2 is false SWE1.02 / ExpCompare.java Software Development 1 // 2018W // 8
ARITHMETIC OPERATORS :: OVERVIEW Operator Name Meaning == Equal to a == b returns true if a is equal to b!= Not equal to a!= b returns true if a is not equal to b > Greater than a > b returns true if a is greater than b < Less than a < b returns true if a is less than b >= Greater than or equal to a >= b returns true if a is greater than b or equal to b <= Less than or equal to a <= b returns true if a is less than b or equal to b Do not confuse == (equal to) with = (assignment)! These operators are only suited for primitive data types, e.g. do not use it for strings or arrays! Software Development 1 // 2018W // 9
ASSIGNMENT OPERATORS Assignment operators assign a value to a variable. = is the simple assignment operators There are many assignment operators with side effects: +=, -=, *=, /=, %=, ^=, &=, =, <<=, >>= and >>>= a += b is identical to a = a + b; a -= b is identical to a = a - b; a *= b is identical to a = a * b; Example: int a = 3, b = 4, c = 5, d; c += d = a + b; // d is 7 // c is 12 Software Development 1 // 2018W // 10
ASSIGNMENT OPERATORS :: OVERVIEW Operator Name Meaning = Simple assignment a = b assigns the value of b to a += Assignment with addition a += b assigns the result of a + b to a -= Assignment with subtraction a -= b assigns the result of a - b to a *= Assignment with multiplication a *= b assigns the result of a * b to a /= Assignment with division a /= b assigns the result of a / b to a %= Assignment with modulo a %= b assigns the result of a % b to a &= Assignment with AND a &= b assigns the result of a & b to a = Assignment with OR a = b assigns the result of a b to a ^= Assignment with XOR a ^= b assigns the result of a ^ b to a Assignment operators always return the assigned value, which means they can be used in further expressions or cascaded, e.g. int a = b += 5; Software Development 1 // 2018W // 11
LOGICAL OPERATORS Logical operators evaluate boolean values: mostly binary infix operators, only! is unary operands and the resulting data type are boolean Operations: AND: && (with Short-Circuit-Evaluation), & (no SCE) OR: (with Short-Circuit-Evaluation), (no SCE) NOT:! (unary) XOR: ^ Short-Circuit-Evaluation (SCE): a && b: If a already evaluates to false, there is no need to evaluate b, since a AND b is definitely false. But if b has side effects, e.g. a && ++x > 1, it may be important to evaluate it anyway. a && b will skip evaluation of b if a is false a & b will always evaluate both a and b Software Development 1 // 2018W // 12
LOGICAL OPERATORS :: EXAMPLE // 2 new date values (year, month, day) int y1 = 2007, m1 = 6, d1 = 10; int y2 = 2007, m2 = 7, d2 = 13; // check if first date is earlier than second date boolean earlier = (y1 < y2) (y1 == y2 && m1 < m2) (y1 == y2 && m1 == m2 && d1 < d2); && false true false false false true false true false true false false true true true true // Short-Circuit-Evaluation: last line of this expression // will not be evaluated in this example SWE1.02 / ExpLogical.java Software Development 1 // 2018W // 13
LOGICAL OPERATORS :: OVERVIEW Operator Name Meaning! Logical NOT && & AND with SCE AND without SCE OR with SCE OR without SCE ^ XOR (no need for SCE)!a evaluates to false if a is true, and to true if a is false a && b evaluates to true if both a and b are true. If a is false, b is not evaluated a & b evaluates to true if both a and b are true. Always evaluates both a and b a b evaluates to true if either a or b are true. If a is true, b is not evaluated. a b evaluates to true if either a or b are true. Always evaluates both a and b a ^ b evaluates to true if a and b are not equal. Always needs to evaluate both a and b Software Development 1 // 2018W // 14
BITWISE OPERATORS Bitwise operators combine integer numbers on a bit level: mostly binary infix operators, only ~ is unary accept all integer primitive data types as operands & 0 1 0 1 ^ 0 1 ~ 0 1 0 0 0 0 0 1 0 0 1 1 0 1 0 1 1 1 1 1 1 0 Operations: AND: & OR: XOR: ^ NOT: ~ (unary) Example: byte a = 3, b = 9; System.out.println(a & b); System.out.println(a b); System.out.println(a ^ b); 00000011 decimal 3 00001001 decimal 9 ======== AND: 00000001 decimal 1 OR: 00001011 decimal 11 XOR: 00001010 decimal 10 SWE1.02 / ExpBitOp.java Software Development 1 // 2018W // 15
BIT SHIFT OPERATORS Bit shift operators move the bit representation of integer numbers to the left or right, inserting 0 on one side and discarding the bit at the other side. binary infix operators operands can be any integer data type Operations: Signed left shift: a << n Moves all bits in a by n to the left, inserting 0 on the right. Signed right shift: a >> n Moves all bits in a by n to the right, inserting the sign bit on the left. Unsigned right shift: a >>> n Moves all bits in a by n to the right, inserting 0 on the left. Optimization: a << n is equivalent to a multiplication with 2 n a >> n is equivalent to a division by 2 n Shift operations are faster than arithmetic operations. Compilers usually use this fact in their optimization process. Software Development 1 // 2018W // 16
BIT SHIFT OPERATORS: EXAMPLE public final class Integer extends Number implements Comparable<Integer> { final static char[] digits = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z' }; Characters for Integer-String conversion Public conversion methods public static String tohexstring(int i) { return tounsignedstring(i, 4); } public static String tooctalstring(int i) { return tounsignedstring(i, 3); } public static String tobinarystring(int i) { return tounsignedstring(i, 1); } private static String tounsignedstring(int i, int shift) { char[] buf = new char[32]; int charpos = 32; int radix = 1 << shift; int mask = radix - 1; do { buf[--charpos] = digits[i & mask]; i >>>= shift; } while (i!= 0); Actual implementation: mask the first 1-4 bits convert to text shift by same number of bits to the right repeat } } return new String(buf, charpos, (32 - charpos)); java.lang.integer Software Development 1 // 2018W // 17
STRING-CONCATENATION The + operator can be used to concatenate Strings. If one of the operands is not of type String, it will be converted to a String. Example: int age = 27; System.out.println("Age: " + age + " years"); Convert int age to String. Concatenate 3 Strings. Concatenate 3 Strings. Output: Age: 27 years Software Development 1 // 2018W // 18
CONDITIONAL EXPRESSIONS Conditional expressions allow to include alternatives in expressions: condition? alternative1 : alternative2 The condition needs to be of type boolean The alternatives need to be of the same type, or the compiler must be able to convert them to the same type (e.g. Strings and primitive types) If the condition is true, alternative1 is evaluated, otherwise alternative2. Every conditional expression can also be formulated as a branching statement (if-else; more on that later in Control Structures ). Conditional expressions are more compact and can be an elegant alternative to if-else, but: Avoid complex conditional expressions, they have a very negative impact on readability of code Software Development 1 // 2018W // 19
CONDITIONAL EXPRESSIONS :: EXAMPLE int totalamount = 200, count = 0; // Avoid division by zero int singleamount = count == 0? 0 : totalamount / count; // Do exactly the same with branching if (count == 0) singleamount = 0; else singleamount = totalamount / count; Identical effect as the conditional expression above. // Output "--" if count is zero System.out.println("Single amount: " + (count == 0? "--" : singleamount)); SWE1.02 / ExpConditional.java Software Development 1 // 2018W // 20
OPERATOR PRECEDENCE Usually operators are evaluated from left to right, with a few exceptions: Assignment operators are evaluated from right to left Evaluation strictly follows operator precedence, similar to mathematical expressions, e.g. in 5 + 3 * 3 + 1 the multiplication has precedence and therefore the result is 15. Parentheses are used to explicitly group operations and change the default behavior, e.g. in (5 + 3) * (3 + 1) the additions have precedence, the result is 24. Software Development 1 // 2018W // 21
OPERATOR PRECEDENCE :: EXAMPLES int line = 1; // On even line numbers, output a single separator line, // on odd line numbers, a double separator line. // Additionally increase the line number by 1. System.out.println((line++ 1) == 0? "---" : "==="); // Output: === // Value of line: 2 Parentheses required: == has precedence before // + has precedence before << // +, << have precedence before > System.out.println("Greater than 10?: " + (3 + 3 << 1 > 10) ); // Output: Greater than 10?: true int a = 2, b; // Assignments are evaluated from right to left: // first b = 8, then a += b a += b = 8; // Invalid: (a += b) = 8; // It is not allowed to use expressions (includes parentheses) // on the left side of an assignment! SWE1.02 / OpPriority.java Software Development 1 // 2018W // 22
Typecasts
TYPE CASTS Assigning variables or expressions with a smaller numeric data type to a variable with a larger data type can be done without any explicit instructions. The data type is automatically (implicitly) and without any loss of data or precision converted. In case a variable or expressions with larger numeric data type needs to be assigned to a variable with smaller numeric data, the necessary conversion needs to be stated explicitly, since this might involve loss of data or precision. Example: int birthdate = 1982; int today = 2012; // valid assignment: int to long long agel = today - birthdate; // assignment int to byte: requires type cast! byte ageb = (byte)(today - birthdate); // Compiler error without type cast: // TempRun.java:12: possible loss of precision // found : int // required: byte // byte ageb = today - birthdate; Software Development 1 // 2018W // 24
IMPLICIT TYPE CASTS Implicit type casts are possible from smaller to larger data types: byte short int long float double char Implicit cast from long to float potentially involves a loss of precision. A cast from char to short would not involve a loss of precision (both are 16 bit integers), but is still not allowed. Software Development 1 // 2018W // 25
EXPLICIT TYPE CASTS Example: Ariane 5 Flight 501 (June 4, 1996) Working code for the Ariane 4 rocket is reused in the Ariane 5, but Ariane 5 was faster (Ariane 5's faster engines trigger a bug in an arithmetic routine inside the rocket's flight computer) The error is in the code that converts a 64-bit floating-point number to a 16-bit signed integer (max. 2^15=32,768). The faster engines cause the 64-bit numbers to be larger in the Ariane 5 than in the Ariane 4, triggering an overflow condition that results in the flight computer crashing 36.7sec. after take off Backup computer crashes (same software!), followed 0.05 seconds later by a crash of the primary computer. As a result of these crashed computers, the rocket's primary processor overpowers the rocket's engines and causes the rocket to disintegrate 40 seconds after launch.
EXPLICIT TYPE CASTS Explicit type casts are performed by preceding the variable or expression x with the new data type in parentheses: (type)x Type casts often involve data loss Data loss does not generate any kind of warning or error Example: type cast from short to byte, in this case without data loss 0000000000110001 (16 bits, value is 49) --------00110001 ( 8 bits, value is 49) 1111111111110001 (16 bits, value is -15) --------11110001 ( 8 bits, value is -15) Software Development 1 // 2018W // 27
EXPLICIT TYPE CASTS Example: type cast from short to byte, in this case with data loss 0000001000000010 (16 bits, value is 514) --------00000010 ( 8 bits, value is 2) Example: short a = -255; byte b = (byte)a; System.out.println(b); float f = 1.9; int i = (int)f; System.out.println(i); Output: 1 1 // type cast short -> byte // type cast float -> int Cast from floating point to integer number: cuts off fractional part, no rounding! Software Development 1 // 2018W // 28
Reference
OVERVIEW :: RESULTING DATA TYPES OF ARITHMETIC OPERATIONS + - * / % char byte short int long float double char int int int int long float double byte int int int int long float double short int int int int long float double int int int int int long float double long long long long long long float double float float float float float float float double double double double double double double double double Software Development 1 // 2018W // 30
OVERVIEW :: OPERATOR PRECEDENCE Category Operators 0 assignment = += -= *= /= %= ^= &= = <<= >>= >>>= 1 conditional operators? : 2 logical OR 3 logical AND && 4 bitwise OR 5 bitwise XOR ^ 6 bitwise AND & 7 equality operators ==!= 8 relational operators < < <= >= instanceof 9 bit shift operators << >> >>> 10 additive operators + - 11 multiplicative operators * / % 12 instantiation or type cast new (type)x 13 unary operators ++x --x +x -x! ~ 14 postfix operators x++ x-- []. Software Development 1 // 2018W // 31
SOFTWARE DEVELOPMENT 1 Operators 2018W (Institute of Pervasive Computing, JKU Linz)