algoz
Chapters/01 Java basics/Operators

Operators

Predict every operator's result exactly, from arithmetic to masked bitwise shifts.

You'll gain
Predict every operator's result exactlyeven with negatives and bit shifts
Practice
Sheet coming sooncoding problems for this note
Summary

Operators transform values and drive decisions, governed by strict rules for truncation, bit masking, and left-to-right evaluation.

The idea in real life

Think of a checkout counter with a barcode scanner, a weighing scale, and a cash register. Each tool performs one specific action on an item: the scale measures weight, the scanner verifies a price, and the register calculates change. Operators work the same way in code, taking inputs, applying one defined rule, and producing a predictable result.

Why it exists

  1. Writing verbose method calls for everyday calculations and comparisons clutters your source code.
  2. Symbolic operators let you express arithmetic, comparisons, and boolean logic in clear, compact expressions.
  3. Computers work with fixed-width binary words, so operations follow exact rounding, sign, and boundary rules rather than pure mathematical ideals.
  4. Knowing these exact rules prevents hidden bugs in array index calculations, binary searches, and conditional branches.

How it works

Arithmetic

Five core operators perform integer calculations with truncation toward zero.

Java provides five arithmetic operators for integers: addition (+), subtraction (-), multiplication (*), division (/), and remainder (%).

When dividing two integers, Java performs integer division. It truncates any fractional part toward zero, discarding the decimal fraction rather than rounding to the nearest integer. For example, 14 / 4 evaluates to 3, not 3.5.

The remainder operator % computes the leftover amount after integer division. For positive numbers, 14 % 4 evaluates to 2 because 4 * 3 + 2 = 14.

Dividing by zero or taking the remainder by zero with integers causes the Java Virtual Machine to halt and throw an ArithmeticException with the message / by zero.

The following program demonstrates these five operators on positive integers. In this program:

  • firstValue is the dividend, set to 14.
  • secondValue is the divisor, set to 4.
  • sum, difference, product, quotient, and remainder store the results of each arithmetic operation.
Main.java
public class Main {
    public static void main(String[] args) {
        int firstValue = 14;
        int secondValue = 4;

        int sum = firstValue + secondValue;
        int difference = firstValue - secondValue;
        int product = firstValue * secondValue;
        int quotient = firstValue / secondValue;
        int remainder = firstValue % secondValue;

        System.out.println("Sum: " + sum);
        System.out.println("Difference: " + difference);
        System.out.println("Product: " + product);
        System.out.println("Quotient: " + quotient);
        System.out.println("Remainder: " + remainder);
    }
}
Output
Sum: 18
Difference: 10
Product: 56
Quotient: 3
Remainder: 2

Increment and decrement

Prefix updates before yielding a value; postfix updates after.

The increment operator (++) increases an integer variable by 1, and the decrement operator (--) decreases it by 1. Both operators can appear in two forms:

  • Prefix (++count or --count): updates the variable first, then yields the new value.
  • Postfix (count++ or count--): yields the current value first, then updates the variable in memory.

When used as an independent statement (such as count++; on its own line), prefix and postfix forms produce the exact same outcome: the variable changes by 1.

The difference matters when you place the expression inside a larger statement or assignment. In int prefixResult = ++count;, count increments from 5 to 6, and prefixResult receives 6. In int postfixResult = count++;, postfixResult receives the current value 6, and count then increments to 7.

The following program traces prefix and postfix evaluation step by step. In this program:

  • count is the variable being modified.
  • prefixResult, postfixResult, and decrementResult capture the value returned by each expression.
Main.java
public class Main {
    public static void main(String[] args) {
        int count = 5;

        int prefixResult = ++count;
        System.out.println("Prefix evaluated: " + prefixResult + ", count: " + count);

        int postfixResult = count++;
        System.out.println("Postfix evaluated: " + postfixResult + ", count: " + count);

        int decrementResult = --count;
        System.out.println("Decrement evaluated: " + decrementResult + ", count: " + count);
    }
}
Output
Prefix evaluated: 6, count: 6
Postfix evaluated: 6, count: 7
Decrement evaluated: 6, count: 6

Compound assignment

Combine calculation with assignment while applying an implicit cast.

Compound assignment operators combine an operation with assignment in a single token. Java includes +=, -=, *=, /=, %=, &=, |=, ^=, <<=, >>=, and >>>=.

The expression total += 5; is equivalent in value to total = total + 5;.

However, compound assignment operators contain a hidden narrowing cast defined in section 15.26.2 of the Java Language Specification (JLS). An expression of the form E1 op= E2 is equivalent to E1 = (T)((E1) op (E2)), where T is the type of E1.

This implicit cast means compound assignments compile in situations where a standard assignment fails. Adding a literal integer to a byte or short normally produces an int result that cannot be assigned back to the smaller type without an explicit cast. With compound assignment, Java inserts the cast automatically. Note 5, Casting and type promotion, examines these numeric promotion rules in depth.

The following program demonstrates compound assignment on an int and illustrates the automatic narrowing cast on a byte. In this program:

  • total is an integer accumulator updated with += and *=.
  • smallValue is a byte starting at 120. Adding 10 exceeds the maximum positive byte value of 127 and wraps to -126 due to the implicit (byte) cast.
Main.java
public class Main {
    public static void main(String[] args) {
        int total = 10;
        total += 5;
        total *= 2;
        System.out.println("Total: " + total);

        byte smallValue = 120;
        smallValue += 10;
        System.out.println("Wrapped byte value: " + smallValue);
    }
}
Output
Total: 30
Wrapped byte value: -126

Comparison and logical operators

Test relationships between values and combine conditions into booleans.

Comparison operators compare two primitive values and evaluate to a boolean result (true or false):

  • == (equal to) and != (not equal to)
  • < (less than) and > (greater than)
  • <= (less than or equal to) and >= (greater than or equal to)

Logical operators combine boolean expressions:

  • && (conditional AND): returns true only when both operands evaluate to true.
  • || (conditional OR): returns true if at least one operand evaluates to true.
  • ! (logical NOT): inverts a boolean value, turning true into false and false into true.

On primitive types taught in variables and primitive types, == tests whether the stored binary values are equal. On objects, == tests whether both variables point to the same object, not whether the contents match. Comparing object contents, such as text strings, requires .equals(), as covered in note 10, Strings.

The following program tests comparisons and logical operators. In this program:

  • left and right are integer quantities being compared.
  • isLess and isEqual hold relational comparison results.
  • inRange combines two relational checks using &&.
  • isBoundary checks whether either boundary matches using ||.
Main.java
public class Main {
    public static void main(String[] args) {
        int left = 15;
        int right = 20;

        boolean isLess = left < right;
        boolean isEqual = left == right;
        boolean inRange = left > 10 && right <= 25;
        boolean isBoundary = left == 0 || right == 20;

        System.out.println("Is less: " + isLess);
        System.out.println("Is equal: " + isEqual);
        System.out.println("In range: " + inRange);
        System.out.println("Is boundary: " + isBoundary);
    }
}
Output
Is less: true
Is equal: false
In range: true
Is boundary: true

Going deeper

Division and remainder with negative numbers

Integer division truncates toward zero, leaving negative remainders.

When working with negative numbers, Java follows strict rules defined in JLS 15.17.2 (Division Operator) and JLS 15.17.3 (Remainder Operator).

Integer division always rounds toward zero, known as truncation toward zero. The result is the integer closest to zero that does not exceed the mathematical quotient in magnitude:

  • -7 / 2 evaluates to -3 (not -4).
  • 7 / -2 evaluates to -3.
  • -7 / -2 evaluates to 3.

The remainder operator % is strictly bound to the division operator by the algebraic identity: (a / b) * b + (a % b) == a

Because -7 / 2 is -3, the product (-3) * 2 is -6. To satisfy the identity and reach -7, the remainder must be -1:

  • -7 % 2 evaluates to -1.
  • 7 % -2 evaluates to 1.

The sign of a % b always matches the sign of the dividend a, regardless of the sign of the divisor b.

This behavior creates a trap when wrapping array indexes in circular buffers or cyclic data structures. If you step backward with (index - 1) % length and index is 0, the expression evaluates to -1 % length, which is -1. Passing -1 as an array index throws an ArrayIndexOutOfBoundsException.

To solve this, Java 8 added Math.floorDiv and Math.floorMod to java.lang.Math:

  • Math.floorDiv(a, b) rounds down toward negative infinity (floor rounding). Math.floorDiv(-7, 2) gives -4.
  • Math.floorMod(a, b) returns the remainder using floor division. Math.floorMod(-7, 2) gives 1.

When the divisor b is positive, Math.floorMod(a, b) is guaranteed to return a non-negative value between 0 and b - 1.

The following program compares standard division and remainder with Math.floorDiv and Math.floorMod. In this program:

  • dividend is the numerator, set to -7.
  • divisor is the denominator, set to 2.
  • standardDiv and standardRem hold the results from / and %.
  • floorDivResult and floorModResult hold the results from the Math methods.
Main.java
public class Main {
    public static void main(String[] args) {
        int dividend = -7;
        int divisor = 2;

        int standardDiv = dividend / divisor;
        int standardRem = dividend % divisor;
        int floorDivResult = Math.floorDiv(dividend, divisor);
        int floorModResult = Math.floorMod(dividend, divisor);

        System.out.println("Standard division: " + standardDiv);
        System.out.println("Standard remainder: " + standardRem);
        System.out.println("Math.floorDiv: " + floorDivResult);
        System.out.println("Math.floorMod: " + floorModResult);
    }
}
Output
Standard division: -3
Standard remainder: -1
Math.floorDiv: -4
Math.floorMod: 1

Short-circuiting

Logical operators skip right-hand operands when the outcome is certain.

Java's conditional operators && (JLS 15.23) and || (JLS 15.24) employ short-circuit evaluation. They only evaluate the right-hand operand if the left-hand operand does not fully determine the result:

  • In left && right, if left evaluates to false, the entire expression must be false. The right-hand operand is skipped completely.
  • In left || right, if left evaluates to true, the entire expression must be true. The right-hand operand is skipped completely.

This guarantee makes short-circuiting a standard guard pattern across algorithms. You can place a bounds check or a null check on the left, and an array read or method call on the right. If the boundary check fails, the dangerous access on the right never executes.

The following program demonstrates short-circuit protection when inspecting an array. In this program:

  • nums is an array of 3 elements, valid from index 0 to 2.
  • index is set to 5, which is outside the array.
  • The condition index < nums.length && nums[index] > 0 evaluates index < nums.length to false and skips nums[index], avoiding an index exception.
Main.java
public class Main {
    public static void main(String[] args) {
        int[] nums = {10, 20, 30};
        int index = 5;

        if (index < nums.length && nums[index] > 0) {
            System.out.println("Element is positive: " + nums[index]);
        } else {
            System.out.println("Index is outside array bounds; access skipped safely.");
        }
    }
}
Output
Index is outside array bounds; access skipped safely.

Bit operators

Manipulate individual bits directly with bitwise logic and shifts.

Bitwise operators manipulate the underlying binary representation of integer values:

  • & (bitwise AND): bit is 1 if both corresponding input bits are 1.
  • | (bitwise OR): bit is 1 if either input bit is 1.
  • ^ (bitwise XOR): bit is 1 if the input bits differ.
  • ~ (bitwise NOT): inverts every bit in the number, turning 0s to 1s and 1s to 0s.
  • << (signed left shift): shifts bits left, filling emptied low bits with 0. Shifting left by 1 multiplies an integer by 2 (as long as it does not overflow).
  • >> (signed right shift): shifts bits right, copying the sign bit into vacated high positions. This arithmetic shift preserves negative signs.
  • >>> (unsigned right shift): shifts bits right, filling vacated high positions with 0 regardless of the sign bit.

The following table summarizes these operations on small binary values:

OperatorNameExampleBinary operationResult
&Bitwise AND5 & 30101 & 00111 (0001)
|Bitwise OR5 | 30101 | 00117 (0111)
^Bitwise XOR5 ^ 30101 ^ 00116 (0110)
~Bitwise NOT~5~(...00000101)-6 (...11111010)
<<Signed left shift5 << 10101 << 110 (1010)
>>Signed right shift-8 >> 111111000 >> 1-4 (11111100)
>>>Unsigned right shift-8 >>> 11111...1000 >>> 12147483644

Chapter 09 explores bit manipulation techniques, bit masks, and binary flags in depth.

The following program tests each bitwise and shift operator. In this program:

  • firstMask is 5 (binary 0101).
  • secondMask is 3 (binary 0011).
  • negativeValue is -8, used to contrast signed right shift (>>) with unsigned right shift (>>>).
Main.java
public class Main {
    public static void main(String[] args) {
        int firstMask = 5;
        int secondMask = 3;

        System.out.println("AND: " + (firstMask & secondMask));
        System.out.println("OR: " + (firstMask | secondMask));
        System.out.println("XOR: " + (firstMask ^ secondMask));
        System.out.println("NOT: " + (~firstMask));
        System.out.println("Left shift: " + (firstMask << 1));

        int negativeValue = -8;
        System.out.println("Signed right shift: " + (negativeValue >> 1));
        System.out.println("Unsigned right shift: " + (negativeValue >>> 1));
    }
}
Output
AND: 1
OR: 7
XOR: 6
NOT: -6
Left shift: 10
Signed right shift: -4
Unsigned right shift: 2147483644

Precedence

Precedence rules decide evaluation grouping, but parentheses make it certain.

When an expression contains several operators, Java uses precedence rules to determine how operands group together. Operators on higher precedence levels bind tighter than operators on lower levels.

The following table lists the operator precedence levels that appear most frequently in algorithm implementations, ordered from highest priority (evaluates first) to lowest:

LevelOperatorsDescriptionAssociativity
1expr++ expr--Postfix increment and decrementLeft to right
2++expr --expr + - ~ !Prefix operators, unary plus/minus, NOTRight to left
3* / %MultiplicativeLeft to right
4+ -AdditiveLeft to right
5<< >> >>>Bitwise shiftsLeft to right
6< > <= >=Relational comparisonsLeft to right
7== !=Equality checksLeft to right
8&Bitwise ANDLeft to right
9^Bitwise XORLeft to right
10|Bitwise ORLeft to right
11&&Conditional ANDLeft to right
12||Conditional ORLeft to right
13? :Ternary conditionalRight to left
14= += -= *= etc.Assignment operatorsRight to left

Notice that additive operators (+ and -) have higher precedence than shift operators (<< and >>), and relational comparisons have higher precedence than bitwise AND (&).

In 1 << 2 + 1, the addition 2 + 1 runs first, yielding 1 << 3, which evaluates to 8. If your intent was to shift 1 by 2 and then add 1, you must write (1 << 2) + 1 to get 5.

Never rely on subtle precedence rules in interview code. Add parentheses () to make grouping clear and unambiguous to both the compiler and the interviewer.

The following program contrasts default precedence grouping against explicit parenthesization. In this program:

  • unbracketed relies on default operator precedence (+ before <<).
  • bracketed uses parentheses to force the bit shift to run before the addition.
Main.java
public class Main {
    public static void main(String[] args) {
        int unbracketed = 1 << 2 + 1;
        int bracketed = (1 << 2) + 1;

        System.out.println("Without brackets (1 << 2 + 1): " + unbracketed);
        System.out.println("With brackets ((1 << 2) + 1): " + bracketed);
    }
}
Output
Without brackets (1 << 2 + 1): 8
With brackets ((1 << 2) + 1): 5

Under the hood

Evaluation order

Java strictly evaluates expression operands from left to right.

Precedence specifies which operator groups with which operands, but it does not dictate the order in which individual operands are evaluated.

Section 15.7 of the Java Language Specification mandates that Java evaluates the operands of an operator strictly from left to right. Every operand expression is evaluated before any part of the operation itself takes place.

This rule explains why the common puzzle index = index++; leaves index unchanged:

  1. The assignment operator = determines its target variable, index.
  2. The right-hand side expression index++ is evaluated. The value of postfix increment is the original value of index (for example, 0).
  3. The side effect of index++ runs in memory, incrementing the variable index to 1.
  4. The assignment operator = executes, storing the value evaluated in step 2 (0) into index, overwriting the 1.

The variable index ends up with 0. In contrast, index = ++index; evaluates ++index, which updates index to 1 and yields 1, so the assignment writes 1 back to index.

The following program demonstrates left-to-right evaluation order and verifies the behavior of index = index++. In this program:

  • index is initialized to 0 and reassigned with index = index++.
  • index is then reassigned with index = ++index to highlight the contrast.
Main.java
public class Main {
    public static void main(String[] args) {
        int index = 0;
        index = index++;
        System.out.println("After index = index++: " + index);

        index = ++index;
        System.out.println("After index = ++index: " + index);
    }
}
Output
After index = index++: 0
After index = ++index: 1

Shift distances are masked

The JVM keeps only the lowest bits of the shift distance.

JLS 15.19 says that Java uses only the lowest bits of the shift distance.

Java masks the right-hand shift distance operand to keep only its lowest 5 bits for an int (distance & 0x1F, which is distance & 31). For a 64-bit long, it keeps only the lowest 6 bits (distance & 0x3F, which is distance & 63).

This bit masking produces counter-intuitive results:

  • 1 << 32 is computed as 1 << (32 & 31), which is 1 << 0 = 1.
  • 1 << 33 is computed as 1 << (33 & 31), which is 1 << 1 = 2.
  • 1 << 64 is computed as 1 << (64 & 31), which is 1 << 0 = 1.

If you write a loop intending to clear all bits by shifting left by 32 positions (value <<= 32), the value remains completely unchanged. To shift a 64-bit quantity across more than 31 positions, you must use a long literal (1L << 32), which masks by 63 instead of 31.

The following program demonstrates masked shift distances on a 32-bit int. In this program:

  • baseValue is 1.
  • shiftedBy32 shifts baseValue by 32 positions, which masks to a shift of 0.
  • shiftedBy33 shifts baseValue by 33 positions, which masks to a shift of 1.
Main.java
public class Main {
    public static void main(String[] args) {
        int baseValue = 1;

        int shiftedBy32 = baseValue << 32;
        int shiftedBy33 = baseValue << 33;

        System.out.println("1 << 32: " + shiftedBy32);
        System.out.println("1 << 33: " + shiftedBy33);
    }
}
Output
1 << 32: 1
1 << 33: 2

Boolean bitwise operators

Single ampersand and pipe on booleans evaluate both sides unconditionally.

The operators &, |, and ^ are not restricted to integers. When applied to boolean operands (JLS 15.22.2), they perform logical operations:

  • flag1 & flag2 produces true if both flags are true.
  • flag1 | flag2 produces true if either flag is true.
  • flag1 ^ flag2 produces true if the flags have different values (logical XOR).

The critical difference between boolean & and && (and between | and ||) is that single & and | operators never short-circuit. They always evaluate both the left-hand and right-hand operands, regardless of the left-hand result.

If the right-hand operand contains a method call or an array index check, that code executes even when the left side is already false. Writing index < nums.length & nums[index] > 0 causes an ArrayIndexOutOfBoundsException when index equals nums.length, because nums[index] is evaluated unconditionally.

The following program demonstrates boolean bitwise operators. In this program:

  • firstFlag is true and secondFlag is false.
  • andResult, orResult, and xorResult demonstrate non-short-circuiting logical operations.
Main.java
public class Main {
    public static void main(String[] args) {
        boolean firstFlag = true;
        boolean secondFlag = false;

        boolean andResult = firstFlag & secondFlag;
        boolean orResult = firstFlag | secondFlag;
        boolean xorResult = firstFlag ^ secondFlag;

        System.out.println("Bitwise AND on booleans: " + andResult);
        System.out.println("Bitwise OR on booleans: " + orResult);
        System.out.println("Bitwise XOR on booleans: " + xorResult);
    }
}
Output
Bitwise AND on booleans: false
Bitwise OR on booleans: true
Bitwise XOR on booleans: true

Overflow with Integer.MIN_VALUE

Dividing the minimum integer by negative one overflows silently.

In Java's two's complement representation, a 32-bit signed int ranges from -2,147,483,648 (Integer.MIN_VALUE) to +2,147,483,647 (Integer.MAX_VALUE). There are more negative numbers than positive numbers, so the negation of Integer.MIN_VALUE cannot fit in a 32-bit signed integer.

According to JLS 15.17.2, integer division does not throw an exception on overflow. When you evaluate Integer.MIN_VALUE / -1, mathematical division produces +2,147,483,648. Because this exceeds Integer.MAX_VALUE, the result wraps around in two's complement arithmetic back to Integer.MIN_VALUE (-2,147,483,648).

Similarly, JLS 15.17.3 specifies that remainder with overflow evaluates to zero: Integer.MIN_VALUE % -1 evaluates to 0.

Only division or remainder by zero throws an ArithmeticException. All other boundary overflows wrap silently without generating runtime errors.

The following program demonstrates division and remainder overflow with Integer.MIN_VALUE. In this program:

  • minInt holds Integer.MIN_VALUE.
  • divisionResult shows the silent wrap-around from dividing by -1.
  • remainderResult shows the remainder evaluating to 0.
Main.java
public class Main {
    public static void main(String[] args) {
        int minInt = Integer.MIN_VALUE;

        int divisionResult = minInt / -1;
        int remainderResult = minInt % -1;

        System.out.println("Integer.MIN_VALUE / -1: " + divisionResult);
        System.out.println("Integer.MIN_VALUE % -1: " + remainderResult);
    }
}
Output
Integer.MIN_VALUE / -1: -2147483648
Integer.MIN_VALUE % -1: 0

In Java

The following complete program combines safe index wrapping, short-circuit guard checks, and midpoint calculation without overflow into three utility methods.

Main.java
public class Main {
    // Returns a valid non-negative index in the range [0, length - 1].
    static int wrapIndex(int index, int length) {
        return Math.floorMod(index, length);
    }

    // Returns the element at index, or -1 if the index is out of bounds.
    static int safeElement(int[] nums, int index) {
        if (index >= 0 && index < nums.length) {
            return nums[index];
        }
        return -1;
    }

    // Returns the average of left and right without integer overflow.
    static int calculateMidpoint(int left, int right) {
        return (left + right) >>> 1;
    }

    public static void main(String[] args) {
        int[] nums = {10, 20, 30, 40, 50};

        int stepBack = wrapIndex(-1, nums.length);
        int validItem = safeElement(nums, 2);
        int missingItem = safeElement(nums, 10);

        int left = 2_000_000_000;
        int right = 2_000_000_000;
        int mid = calculateMidpoint(left, right);

        System.out.println("Wrapped index for -1: " + stepBack);
        System.out.println("Safe element at 2: " + validItem);
        System.out.println("Safe element at 10: " + missingItem);
        System.out.println("Midpoint without overflow: " + mid);
    }
}
Output
Wrapped index for -1: 4
Safe element at 2: 30
Safe element at 10: -1
Midpoint without overflow: 2000000000

Traps

  1. Using % to wrap around array indexes with negative values

    The remainder operator keeps the sign of the left operand. When index is 0, (0 - 1) % n is -1, and using it as an index throws ArrayIndexOutOfBoundsException. Use Math.floorMod(index - 1, n) or ((index - 1) % n + n) % n.

    ✕ WRONGint prev = (index - 1) % n;
    ✓ RIGHTint prev = Math.floorMod(index - 1, n);
  2. Assigning a postfix increment back to the same variable

    Java evaluates the right-hand expression first and saves the original value. The postfix operator increments the variable in memory, but the assignment immediately overwrites the variable with the saved original value, leaving it unchanged.

    ✕ WRONGcount = count++;
    ✓ RIGHTcount++;
  3. Using single & instead of && in guard checks

    A single & on booleans does not short-circuit: it always evaluates both sides. If index is out of bounds, nums[index] still runs and throws ArrayIndexOutOfBoundsException.

    ✕ WRONGif (index < nums.length & nums[index] > 0)
    ✓ RIGHTif (index < nums.length && nums[index] > 0)
  4. Treating ^ as exponentiation instead of bitwise XOR

    In Java, ^ is exclusive OR, not a power. base ^ 2 flips one bit of base instead of squaring it.

    ✕ WRONGint squared = base ^ 2;
    ✓ RIGHTint squared = base * base;
  5. Shifting by 32 bits or more on an int

    For an int, the shift distance is masked with 31, so mask << 32 runs as mask << 0 and leaves the value unchanged.

    ✕ WRONGint cleared = mask << 32;
    ✓ RIGHTint cleared = 0;
  6. Mixing addition and bit shifts without parentheses

    + binds tighter than <<, so 1 << 2 + 1 groups as 1 << 3, which is 8, not 5.

    ✕ WRONGint result = 1 << 2 + 1;
    ✓ RIGHTint result = (1 << 2) + 1;
  7. Calculating binary search midpoint with (left + right) / 2

    This overflow is explained in variables and primitive types. The operator view: (left + right) >>> 1 also works, because >>> treats the wrapped sum as unsigned.

    ✕ WRONGint mid = (left + right) / 2;
    ✓ RIGHTint mid = left + (right - left) / 2;
  8. Integer division discarding fractional parts

    When both operands are integers, / does integer division before the result is stored in the double. Cast one operand to double first.

    ✕ WRONGdouble ratio = numerator / denominator;
    ✓ RIGHTdouble ratio = (double) numerator / denominator;
AlgozSet in Geist & Geist MonoJava track