skip to content

In Java, what does an expression like 1 << 33 evaluate to, and why? Explain shift-distance modulo behavior.

level: seniorimportance: should knowfreq 40%

answer

  1. int: distance mod 32 (low 5 bits)
  2. long: distance mod 64 (low 6 bits)
  3. 1 << 32 == 1, not 0
  4. modulus follows LEFT operand type
  5. negative distance wraps too

basics

~20 s

The shift amount is reduced using a remainder. For int it's the amount mod 32, for long it's mod 64. So 1 << 33 is the same as 1 << 1 = 2, not 0.

solid answer

~50 s

Java does not let you shift an int by 32 or more positions in the naive way. Instead, only the low 5 bits of the shift distance are used for `int` operands (giving an effective distance of distance mod 32), and the low 6 bits for `long` operands (distance mod 64). So `1 << 33` uses 33 & 31 = 1, yielding 2; `1 << 32` uses 0, yielding 1 (a no-op, not 0). Crucially the modulus depends on the type of the *left* operand, not the right: `1 << 64` is `1 << 0 = 1` because the left side is an int, but `1L << 64` is `1L << 0 = 1L`. Negative distances also wrap: `1 << -1` = `1 << 31`. This surprises people expecting a shift of 32+ to zero out the value, so to truly clear a value you must branch or use a wider type.

code

java · 8 lines
java
System.out.println(1 << 33);   // 2   (33 mod 32 = 1)
System.out.println(1 << 32);   // 1   (no-op, NOT 0)
System.out.println(1L << 32);  // 4294967296  (long: mod 64)
System.out.println(1 << -1);   // -2147483648 (-1 & 31 = 31)

// to shift an int by >=32 positions, widen first:
int x = 1;
long wide = ((long) x) << 40;  // 1099511627776

go deeper

for a junior

May not know this rule; can at least recall that very large shift counts behave unexpectedly.

for a middle

Knows int shifts use distance mod 32 and long uses mod 64, and that 1 << 32 == 1.

for a senior

Explains that the modulus is fixed by the left operand's type, handles negative distances, and knows the hardware/JLS rationale.

for a principal

Anticipates this in cross-type or data-driven shift code, designs APIs that guard variable shift distances, and teaches the left-operand-type subtlety.

## The question behind the question Intuitively, shifting a 32-bit `int` left by 32 places should push every bit off the end and leave 0. Java does **not** do that. Understanding why requires knowing how the shift *distance* is interpreted. ## The rule: shift distance is taken modulo the operand width For a shift `x << n`, `x >> n`, or `x >>> n`: - If `x` (the **left** operand) is an `int`, only the **low 5 bits** of `n` are used. Five bits express 0..31, so the effective distance is `n & 31`, i.e. `n mod 32`. - If `x` is a `long`, only the **low 6 bits** of `n` are used: effective distance `n & 63`, i.e. `n mod 64`. The Java Language Specification defines exactly this. It mirrors what the underlying CPU shift instructions (e.g. x86) do, so the JVM can compile a shift to a single hardware instruction. ## Worked examples - `1 << 33`: left operand is `int`, so distance = 33 mod 32 = 1 → result 2. - `1 << 32`: distance = 32 mod 32 = 0 → **no shift**, result 1 (not 0!). - `1 << 31`: distance 31 → `Integer.MIN_VALUE` (the sign bit). - `1L << 64`: left operand is `long`, distance = 64 mod 64 = 0 → result `1L`. - `1L << 65`: distance 65 mod 64 = 1 → result 2L. ## The modulus follows the LEFT operand's type This is the classic trap. `1 << 64` and `1L << 64` differ: the first is an `int` shift (mod 32 → distance 0 → 1), the second a `long` shift (mod 64 → distance 0 → 1) — same here by coincidence, but `1 << 32` (int) = 1 while `1L << 32` (long) = 4294967296. The right operand's type is irrelevant; what matters is whether the value being shifted is `int` or `long`. ## Negative distances Because only the low 5/6 bits are used and they're taken from the two's-complement representation, a negative `n` wraps too: `1 << -1` uses `-1 & 31` = 31, so it equals `1 << 31`. ## Practical consequences - You **cannot** zero out an int by shifting it 32+ times; `x << 32 == x`. To clear, assign 0 or branch on the distance. - A variable shift distance coming from data must be range-checked if you expect 0..width behavior, or you'll get surprising wrap-around. - When shifting an `int` by a distance up to 63 expecting long semantics, widen first: `((long) x) << 40`.

  • Why does the modulus depend on the left operand, not the shift count?
    The result type and the hardware shift width are determined by the value being shifted (int=32, long=64). The shift count is just a number; only its low 5 or 6 bits are read, chosen by the left operand's width.
  • How do you correctly shift an int value by a distance that may be 32 or more?
    Cast the value to long first (so the modulus is 64) if you need up to 63 positions, or special-case distances >= width to produce 0, since a plain int shift wraps.

saying these in an interview costs you the question

  • Thinking 1 << 32 is 0 (it's 1)
  • Believing the right operand's type sets the modulus
  • Assuming a shift of width-or-more clears the value
  • Forgetting to widen an int to long before a large shift

context