CodeDifficulty: Intermediate3 min

Bit Tricks in Python, Java and TypeScript, and Where Their Outputs Differ

Test, set and clear one bit, clear or isolate the lowest set bit, then print the three values where the languages disagree.

Five one-line expressions test, set and clear single bits, where k is a bit's position counted from 0 at the low end. (x >> k) & 1 tests bit k, x | (1 << k) sets it, and x & ~(1 << k) clears it. x & (x - 1) clears the lowest bit that is on, and x & -x keeps only that bit. Each listing runs them on x = 10, then prints three boundary lines, highlighted, whose outputs differ between the languages.

The bit tricks and the boundary lines in three languages

bit_tricks.pypy
x = 10
print("x:", format(x, "08b"))
print("test bit 1:", (x >> 1) & 1)
print("set bit 0:", x | (1 << 0))
print("clear bit 3:", x & ~(1 << 3))
print("clear lowest set bit:", x & (x - 1))
print("isolate lowest set bit:", x & -x)
print("1 << 31:", 1 << 31)
print("(2**32 + 5) | 0:", (2**32 + 5) | 0)
print("-5 & 0xFFFFFFFF:", -5 & 0xFFFFFFFF)
OutputRan with python:3.14.8-slim-trixie (Python 3.14.8)
x: 00001010
test bit 1: 1
set bit 0: 11
clear bit 3: 2
clear lowest set bit: 8
isolate lowest set bit: 2
1 << 31: 2147483648
(2**32 + 5) | 0: 4294967301
-5 & 0xFFFFFFFF: 4294967291
BitTricks.javajava
public class BitTricks {
    public static void main(String[] args) {
        int x = 10;
        System.out.println("x: " + String.format("%8s", Integer.toBinaryString(x)).replace(' ', '0'));
        System.out.println("test bit 1: " + ((x >> 1) & 1));
        System.out.println("set bit 0: " + (x | (1 << 0)));
        System.out.println("clear bit 3: " + (x & ~(1 << 3)));
        System.out.println("clear lowest set bit: " + (x & (x - 1)));
        System.out.println("isolate lowest set bit: " + (x & -x));
        System.out.println("1 << 31: " + (1 << 31));
        System.out.println("1L << 31: " + (1L << 31));
        System.out.println("-5 >>> 1: " + (-5 >>> 1));
    }
}
OutputRan with eclipse-temurin:25.0.4.1_1-jdk-noble (Java 25.0.4.1)
x: 00001010
test bit 1: 1
set bit 0: 11
clear bit 3: 2
clear lowest set bit: 8
isolate lowest set bit: 2
1 << 31: -2147483648
1L << 31: 2147483648
-5 >>> 1: 2147483645
bit_tricks.tsts
const x = 10;
console.log("x:", (x >>> 0).toString(2).padStart(8, "0"));
console.log("test bit 1:", (x >> 1) & 1);
console.log("set bit 0:", x | (1 << 0));
console.log("clear bit 3:", x & ~(1 << 3));
console.log("clear lowest set bit:", x & (x - 1));
console.log("isolate lowest set bit:", x & -x);
console.log("1 << 31:", 1 << 31);
console.log("(2 ** 32 + 5) | 0:", (2 ** 32 + 5) | 0);
console.log("-5 >>> 1:", -5 >>> 1);
OutputRan with node:24.22.0-trixie-slim (Node 24.22.0), TypeScript 5.9.3
x: 00001010
test bit 1: 1
set bit 0: 11
clear bit 3: 2
clear lowest set bit: 8
isolate lowest set bit: 2
1 << 31: -2147483648
(2 ** 32 + 5) | 0: 5
-5 >>> 1: 2147483645

The first six lines agree in all three languages, and the boundary lines do not. 1 << 31 is 2147483648 in Python, whose integers grow, and −2147483648 in Java and TypeScript, where bit 31 is the sign bit of a 32-bit number. TypeScript's (2 ** 32 + 5) | 0 is 5, because | first converts its operands to 32 bits and drops everything above, where Python keeps 4294967301. Java's 1L << 31 shifts a 64-bit long and gives 2147483648. The unsigned right shift >>>, in Java and TypeScript, fills the vacated high bits with 0, so -5 >>> 1 is 2147483645. Python has no >>>; masking with 0xFFFFFFFF shows the 32-bit pattern of a negative number, 4294967291 for −5.

Printing bits differs too. Python uses format(x, "08b"), Java Integer.toBinaryString, and TypeScript (x >>> 0).toString(2), because toString(2) on a negative number prints a minus sign rather than its bits. Python counts the bits that are on with int.bit_count(), from version 3.10, and Java with Integer.bitCount; TypeScript has no built-in count. Every trick is O(1).