โ˜• Java

Java Number System

A complete guide to the Java Number System โ€” binary, octal, decimal, hexadecimal representations, base conversion methods, number literals, two's complement for negative numbers, bitwise and shift operators, and real-world applications with practical examples.

๐Ÿ“…

Last Updated

March 2026

โฑ๏ธ

Read Time

18 min

๐ŸŽฏ

Level

Beginner to Intermediate

What is a Number System?

A number system is a mathematical framework for representing quantities using a fixed set of digits and a base (also called radix). The base determines how many unique digits are available and how positional value is assigned to each digit. Every position in a number represents a power of the base โ€” just like how the '3' in '300' means 3 ร— 10ยฒ in decimal.

Computers โ€” including the JVM that runs Java programs โ€” operate entirely on binary (base 2): every piece of data, every instruction, every character in memory is ultimately represented as a sequence of bits (0s and 1s). As a Java developer, understanding number systems means understanding how the data you write in code (int x = 255) is actually stored and manipulated at the hardware level โ€” and how to work with that binary representation directly when needed.

Java natively supports four number systems in source code: decimal (base 10, everyday use), binary (base 2, bit-level operations), octal (base 8, legacy Unix permissions), and hexadecimal (base 16, memory addresses, colour codes, cryptographic hashes). All four compile to identical machine instructions โ€” they are simply different ways of writing the same integer value in source code.

Four Number Systems Supported in Java

Here is a concise overview of each number system Java supports, including its base, digit set, Java prefix, and primary use case:

SystemBaseDigits UsedJava PrefixExample (= 255)Primary Use Case
Decimal100 โ€“ 9None (default)255Everyday arithmetic, user-facing numbers
Binary20, 10b or 0B0b11111111Bit manipulation, flags, hardware interfaces
Octal80 โ€“ 70 (leading zero)0377Unix/Linux file permissions, legacy systems
Hexadecimal160โ€“9, Aโ€“F (or aโ€“f)0x or 0X0xFFMemory addresses, colour codes, byte values, crypto
โ˜• JavaAll Four Representations of the Same Value
public class NumberSystems {
    public static void main(String[] args) {

        // All four literals represent the same value: 255
        int decimal     = 255;          // Decimal     (base 10)
        int binary      = 0b11111111;   // Binary      (base 2)  โ€” prefix 0b
        int octal       = 0377;          // Octal       (base 8)  โ€” leading 0
        int hexadecimal = 0xFF;          // Hexadecimal (base 16) โ€” prefix 0x

        System.out.println("Decimal     : " + decimal);
        System.out.println("Binary      : " + binary);
        System.out.println("Octal       : " + octal);
        System.out.println("Hexadecimal : " + hexadecimal);

        // All are equal โ€” same bits in memory
        System.out.println("All equal?  : " + (decimal == binary && binary == octal && octal == hexadecimal));

        // Java 7+ โ€” underscores in numeric literals for readability
        int creditCard  = 1234_5678_9012_3456;  // decimal with underscores
        int colorRed    = 0xFF_00_00;            // hex with underscores
        int flags       = 0b1010_0101;           // binary with underscores
        System.out.println("\nCredit card : " + creditCard);
        System.out.println("Color Red   : " + colorRed);
        System.out.println("Flags byte  : " + flags);
    }
}

Output

Decimal : 255 Binary : 255 Octal : 255 Hexadecimal : 255 All equal? : true Credit card : 1234567890123456 Color Red : 16711680 Flags byte : 165

Why Programmers Need Number Systems

Understanding number systems is not academic theory โ€” it has direct, daily practical applications in professional Java development:

  • โ–ถ

    ๐ŸŽจ Colour Codes and Graphics โ€” RGB colours in web and Android development are written in hexadecimal: #FF5733 means Red=0xFF (255), Green=0x57 (87), Blue=0x33 (51). Java AWT and Android's Color class accept hex values like 0xFF5733.

  • โ–ถ

    ๐Ÿ” Cryptography and Hashing โ€” SHA-256, MD5, and other hash outputs are hex strings: e.g. 'a9993e36476...' Each hex character represents 4 bits (a nibble), making hex the most compact human-readable representation of byte arrays.

  • โ–ถ

    ๐Ÿšฉ Bit Flags and Permissions โ€” Linux file permissions (chmod 755 = rwxr-xr-x) are octal. Java's NIO FilePermissions, Android's Manifest permissions, and network flag fields use bit manipulation where understanding binary layout is essential.

  • โ–ถ

    ๐Ÿง  Memory and Pointer Arithmetic โ€” JVM memory addresses, object references in debugging output (e.g. Object@1b6d3586), and native memory operations via JNI or Java's Unsafe class all use hexadecimal.

  • โ–ถ

    โš™๏ธ Bitwise Operations for Performance โ€” Fast power-of-2 operations, bitmask flags, low-level protocol parsing (TCP headers, USB HID reports), and embedded systems interfaces all require direct binary manipulation.

  • โ–ถ

    ๐Ÿ”ข Binary Data Parsing โ€” Reading binary file formats (PNG, ZIP, class files), network packets, or hardware sensor data requires understanding how bytes (8 bits each) map to integer values across different bases.

Binary vs Octal vs Decimal vs Hexadecimal โ€” Full Comparison

Understanding how the same values look across all four bases builds the mental model needed for base conversion. Here is a reference table of values 0โ€“20 across all four systems:

DecimalBinaryOctalHexadecimal
0000000
1000111
2001022
3001133
4010044
5010155
6011066
7011177
81000108
91001119
10101012A
11101113B
12110014C
13110115D
14111016E
15111117F
160001 00002010
170001 00012111
180001 00102212
190001 00112313
200001 01002414

Key insight: One hexadecimal digit represents exactly 4 binary bits (a nibble). One octal digit represents exactly 3 binary bits. This is why hex is so popular for representing bytes โ€” one byte (8 bits) is always exactly two hex digits (e.g., 0xFF = 1111 1111 = 255).

Number Literals in Java

Java allows integer literals to be written in all four bases directly in source code. Java 7 also added underscore separators inside numeric literals to improve readability โ€” the underscores are ignored by the compiler.

โ˜• JavaAll Java Numeric Literal Formats
public class NumericLiterals {
    public static void main(String[] args) {

        // ---- INTEGER LITERALS ----
        int dec  = 1_000_000;         // decimal  โ€” 1 million
        int bin  = 0b0001_0000;        // binary   โ€” 16
        int oct  = 0755;               // octal    โ€” 493 (Unix rwxr-xr-x)
        int hex  = 0xCAFE_BABE;        // hex      โ€” Java class file magic number

        // ---- LONG LITERALS (suffix L) ----
        long bigDec = 9_876_543_210L;
        long binLng = 0b1111_1111_1111_1111L;  // 65535L
        long hexLng = 0xDEAD_BEEF_CAFEL;

        // ---- FLOAT LITERALS (suffix f) ----
        float  pi   = 3.14_159_265f;
        double dpi  = 3.141_592_653_589_793;

        // ---- SCIENTIFIC NOTATION ----
        double avogadro  = 6.022e23;    // 6.022 ร— 10^23
        double electron  = 1.6e-19;     // 1.6  ร— 10^-19

        // ---- CHAR LITERALS (Unicode hex) ----
        char rupee  = '\u20B9';   // โ‚น โ€” Unicode hex U+20B9
        char omega  = '\u03A9';   // ฮฉ
        char check  = '\u2713';   // โœ“

        System.out.println("dec       = " + dec);
        System.out.println("bin (16)  = " + bin);
        System.out.println("oct (493) = " + oct);
        System.out.printf ("hex magic = %X%n", hex);
        System.out.println("bigDec    = " + bigDec);
        System.out.println("pi float  = " + pi);
        System.out.println("Avogadro  = " + avogadro);
        System.out.println("Rupee sym = " + rupee);
        System.out.println("Check sym = " + check);
    }
}

Output

dec = 1000000 bin (16) = 16 oct (493) = 493 hex magic = CAFEBABE bigDec = 9876543210 pi float = 3.1415927 Avogadro = 6.022E23 Rupee sym = โ‚น Check sym = โœ“

Important rules for underscores in literals: Underscores cannot appear at the start or end of a literal (_255 and 255_ are invalid). They cannot appear adjacent to the decimal point in floating-point literals (3._14 is invalid). They cannot appear before the L, f, or d suffix. Other than these restrictions, underscores can appear anywhere โ€” including in hex, binary, and octal literals.

Java Built-in Conversion Methods

Java's Integer, Long, and String classes provide a complete set of built-in methods for converting between number bases. These are the fastest and most reliable way to perform base conversions in Java.

MethodClassDescriptionExample
toBinaryString(int n)IntegerConverts int to binary String (unsigned)Integer.toBinaryString(25) โ†’ "11001"
toOctalString(int n)IntegerConverts int to octal StringInteger.toOctalString(255) โ†’ "377"
toHexString(int n)IntegerConverts int to hex String (lowercase)Integer.toHexString(255) โ†’ "ff"
toString(int n, int radix)IntegerConverts int to String in any base (2โ€“36)Integer.toString(255, 2) โ†’ "11111111"
parseInt(String s, int r)IntegerParses String in base r to decimal intInteger.parseInt("ff", 16) โ†’ 255
parseInt(String s)IntegerParses decimal String to intInteger.parseInt("255") โ†’ 255
valueOf(String s, int r)IntegerReturns Integer object from String in base rInteger.valueOf("11001", 2) โ†’ 25
bitCount(int n)IntegerReturns count of 1-bits (set bits) in binaryInteger.bitCount(255) โ†’ 8
highestOneBit(int n)IntegerReturns value with only highest bit setInteger.highestOneBit(100) โ†’ 64
lowestOneBit(int n)IntegerReturns value with only lowest bit setInteger.lowestOneBit(12) โ†’ 4
numberOfLeadingZeros(int n)IntegerCounts leading zero bits in 32-bit representationInteger.numberOfLeadingZeros(1) โ†’ 31
numberOfTrailingZeros(int n)IntegerCounts trailing zero bitsInteger.numberOfTrailingZeros(16) โ†’ 4
reverse(int n)IntegerReverses the bit order of the intInteger.reverse(1) โ†’ -2147483648
reverseBytes(int n)IntegerReverses the byte order (endianness swap)Integer.reverseBytes(0x12345678) โ†’ 0x78563412
toBinaryString(long n)LongConverts long to binary StringLong.toBinaryString(100L) โ†’ "1100100"
parseLong(String s, int r)LongParses String in base r to longLong.parseLong("ff", 16) โ†’ 255L
โ˜• JavaBuilt-in Conversion Methods Demo
public class ConversionMethods {
    public static void main(String[] args) {

        int n = 173;

        // Decimal โ†’ Other bases
        System.out.println("Decimal       : " + n);
        System.out.println("โ†’ Binary       : " + Integer.toBinaryString(n));
        System.out.println("โ†’ Octal        : " + Integer.toOctalString(n));
        System.out.println("โ†’ Hexadecimal  : " + Integer.toHexString(n));
        System.out.println("โ†’ Base 5       : " + Integer.toString(n, 5));
        System.out.println("โ†’ Base 36      : " + Integer.toString(n, 36));

        // Other bases โ†’ Decimal
        System.out.println("\nBinary '10101101' โ†’ Decimal: " + Integer.parseInt("10101101", 2));
        System.out.println("Octal  '255'      โ†’ Decimal: " + Integer.parseInt("255", 8));
        System.out.println("Hex    'AD'       โ†’ Decimal: " + Integer.parseInt("AD", 16));

        // Bit information
        System.out.println("\nBit count of 173 : " + Integer.bitCount(n));
        System.out.println("Leading zeros    : " + Integer.numberOfLeadingZeros(n));
        System.out.println("Trailing zeros   : " + Integer.numberOfTrailingZeros(n));
        System.out.println("Highest one bit  : " + Integer.highestOneBit(n));

        // Padded binary string (8-bit padding)
        String padded = String.format("%8s", Integer.toBinaryString(n)).replace(" ", "0");
        System.out.println("\nPadded binary (8-bit): " + padded);

        // Padded hex string (4 digits)
        System.out.printf("Padded hex (4-digit) : %04X%n", n);
    }
}

Output

Decimal : 173 โ†’ Binary : 10101101 โ†’ Octal : 255 โ†’ Hexadecimal : ad โ†’ Base 5 : 1143 โ†’ Base 36 : 4t Binary '10101101' โ†’ Decimal: 173 Octal '255' โ†’ Decimal: 173 Hex 'AD' โ†’ Decimal: 173 Bit count of 173 : 5 Leading zeros : 24 Trailing zeros : 0 Highest one bit : 128 Padded binary (8-bit): 10101101 Padded hex (4-digit) : 00AD

Manual Base Conversion Algorithms

Understanding the manual algorithms behind base conversion is essential for interviews and for understanding what Java's built-in methods do internally. Here are the three most common manual conversion algorithms:

โ˜• JavaManual Base Conversion Algorithms
public class ManualConversions {

    // Algorithm 1: Decimal โ†’ Binary (repeated division by 2)
    static String decimalToBinary(int n) {
        if (n == 0) return "0";
        StringBuilder sb = new StringBuilder();
        int temp = Math.abs(n);
        while (temp > 0) {
            sb.append(temp % 2);   // remainder is 0 or 1
            temp /= 2;             // integer divide by base
        }
        if (n < 0) sb.append("-");
        return sb.reverse().toString();
    }

    // Algorithm 2: Binary String โ†’ Decimal (positional weight sum)
    static int binaryToDecimal(String binary) {
        int decimal = 0;
        int power   = 0;
        for (int i = binary.length() - 1; i >= 0; i--) {
            int bit = binary.charAt(i) - '0';  // '0'โ†’0, '1'โ†’1
            decimal += bit * (int) Math.pow(2, power);
            power++;
        }
        return decimal;
    }

    // Algorithm 3: Decimal โ†’ Any Base (generalised)
    static String decimalToBase(int n, int base) {
        if (n == 0) return "0";
        String digits = "0123456789ABCDEF";
        StringBuilder sb = new StringBuilder();
        int temp = Math.abs(n);
        while (temp > 0) {
            sb.append(digits.charAt(temp % base));
            temp /= base;
        }
        if (n < 0) sb.append("-");
        return sb.reverse().toString();
    }

    public static void main(String[] args) {
        System.out.println("--- Decimal to Binary ---");
        System.out.println("25  โ†’ " + decimalToBinary(25));
        System.out.println("100 โ†’ " + decimalToBinary(100));
        System.out.println("255 โ†’ " + decimalToBinary(255));

        System.out.println("\n--- Binary to Decimal ---");
        System.out.println("11001    โ†’ " + binaryToDecimal("11001"));
        System.out.println("1100100  โ†’ " + binaryToDecimal("1100100"));
        System.out.println("11111111 โ†’ " + binaryToDecimal("11111111"));

        System.out.println("\n--- Decimal to Any Base ---");
        System.out.println("255 base 2  โ†’ " + decimalToBase(255, 2));
        System.out.println("255 base 8  โ†’ " + decimalToBase(255, 8));
        System.out.println("255 base 16 โ†’ " + decimalToBase(255, 16));
        System.out.println("255 base 5  โ†’ " + decimalToBase(255, 5));
    }
}

Output

--- Decimal to Binary --- 25 โ†’ 11001 100 โ†’ 1100100 255 โ†’ 11111111 --- Binary to Decimal --- 11001 โ†’ 25 1100100 โ†’ 100 11111111 โ†’ 255 --- Decimal to Any Base --- 255 base 2 โ†’ 11111111 255 base 8 โ†’ 377 255 base 16 โ†’ FF 255 base 5 โ†’ 2010

Two's Complement โ€” How Java Represents Negative Numbers

Java's primitive integer types (byte, short, int, long) use two's complement binary representation for negative numbers. This is not just theory โ€” it explains exactly why Integer.MAX_VALUE + 1 == Integer.MIN_VALUE (integer overflow), and why Integer.toBinaryString(-1) returns 32 ones.

  • โ–ถ

    Step 1 โ€” Write the binary of the absolute value โ€” For -25: write binary of 25 = 0001 1001 (8-bit)

  • โ–ถ

    Step 2 โ€” Flip all bits (one's complement) โ€” 0001 1001 โ†’ 1110 0110

  • โ–ถ

    Step 3 โ€” Add 1 to the result โ€” 1110 0110 + 1 = 1110 0111 โ€” this is -25 in 8-bit two's complement

โ˜• JavaTwo's Complement โ€” Negative Numbers in Java
public class TwosComplement {
    public static void main(String[] args) {

        // Integer.toBinaryString shows the actual 32-bit two's complement
        System.out.println("Binary of  5  : " + Integer.toBinaryString(5));
        System.out.println("Binary of -5  : " + Integer.toBinaryString(-5));
        System.out.println("Binary of  1  : " + Integer.toBinaryString(1));
        System.out.println("Binary of -1  : " + Integer.toBinaryString(-1));  // 32 ones
        System.out.println("Binary of  0  : " + Integer.toBinaryString(0));

        // Two's complement property: n + (~n) = -1
        int x = 42;
        System.out.println("\nx           = " + x);
        System.out.println("~x (flip)   = " + (~x));
        System.out.println("x + (~x)    = " + (x + (~x)));  // always -1
        System.out.println("-x manual   = " + (~x + 1));    // two's complement
        System.out.println("-x java     = " + (-x));        // same result

        // Integer overflow โ€” two's complement wrap-around
        System.out.println("\nMAX_VALUE     : " + Integer.MAX_VALUE);
        System.out.println("MAX_VALUE + 1  : " + (Integer.MAX_VALUE + 1)); // wraps to MIN_VALUE
        System.out.println("MIN_VALUE      : " + Integer.MIN_VALUE);
        System.out.println("MIN_VALUE - 1  : " + (Integer.MIN_VALUE - 1)); // wraps to MAX_VALUE

        // Bit widths of Java integer types
        System.out.println("\nbyte  range: " + Byte.MIN_VALUE    + " to " + Byte.MAX_VALUE);
        System.out.println("short range: " + Short.MIN_VALUE   + " to " + Short.MAX_VALUE);
        System.out.println("int   range: " + Integer.MIN_VALUE + " to " + Integer.MAX_VALUE);
        System.out.println("long  range: " + Long.MIN_VALUE    + " to " + Long.MAX_VALUE);
    }
}

Output

Binary of 5 : 101 Binary of -5 : 11111111111111111111111111111011 Binary of 1 : 1 Binary of -1 : 11111111111111111111111111111111 Binary of 0 : 0 x = 42 ~x (flip) = -43 x + (~x) = -1 -x manual = -42 -x java = -42 MAX_VALUE : 2147483647 MAX_VALUE + 1 : -2147483648 MIN_VALUE : -2147483648 MIN_VALUE - 1 : 2147483647 byte range: -128 to 127 short range: -32768 to 32767 int range: -2147483648 to 2147483647 long range: -9223372036854775808 to 9223372036854775807

Bitwise Operators in Java

Java provides six bitwise operators that operate on individual bits of integer operands. These are fundamental for bit manipulation, flag management, performance optimisation, and low-level data processing.

OperatorNameOperationExample (5, 3)Result
&Bitwise AND1 only if BOTH bits are 10101 & 00110001 = 1
|Bitwise OR1 if EITHER bit is 10101 | 00110111 = 7
^Bitwise XOR1 if bits are DIFFERENT0101 ^ 00110110 = 6
~Bitwise NOTFlip all bits (unary)~01011010...1010 = -6
<<Left ShiftShift bits left, fill 0s on right5 << 11010 = 10 (ร—2)
>>Right ShiftShift bits right, fill sign bit5 >> 10010 = 2 (รท2)
>>>Unsigned RSShift right, always fill 0s-8 >>> 12147483644
โ˜• JavaBitwise Operators โ€” Practical Demo
public class BitwiseDemo {
    public static void main(String[] args) {

        int a = 0b1010_1100;  // 172
        int b = 0b0011_1111;  //  63

        System.out.printf("a          = %3d  | %s%n", a, Integer.toBinaryString(a));
        System.out.printf("b          = %3d  | %s%n", b, Integer.toBinaryString(b));
        System.out.printf("a & b      = %3d  | %s%n", (a&b),  Integer.toBinaryString(a&b));
        System.out.printf("a | b      = %3d  | %s%n", (a|b),  Integer.toBinaryString(a|b));
        System.out.printf("a ^ b      = %3d  | %s%n", (a^b),  Integer.toBinaryString(a^b));
        System.out.printf("~a         = %3d  | (32-bit two's complement)%n", ~a);

        System.out.println();

        // Common bitwise tricks
        int x = 52;
        System.out.println("--- Bitwise Tricks ---");
        System.out.println("x = " + x + "  binary: " + Integer.toBinaryString(x));

        // Check if even or odd
        System.out.println("Is even? : " + ((x & 1) == 0));  // LSB = 0 โ†’ even

        // Multiply and divide by 2
        System.out.println("x << 1 (ร—2) = " + (x << 1));   // 104
        System.out.println("x >> 1 (รท2) = " + (x >> 1));   // 26
        System.out.println("x << 3 (ร—8) = " + (x << 3));   // 416

        // Check if power of 2
        int p = 64;
        System.out.println(p + " is power of 2? " + ((p & (p - 1)) == 0));

        // Toggle, set, clear a specific bit
        int flags = 0b0000_0000;
        flags |=  (1 << 3);   // SET   bit 3
        System.out.println("After SET  bit 3: " + Integer.toBinaryString(flags));
        flags ^=  (1 << 3);   // TOGGLE bit 3
        System.out.println("After TOGGLE bit 3: " + Integer.toBinaryString(flags));
        flags |=  (1 << 5);   // SET   bit 5
        flags &= ~(1 << 5);   // CLEAR bit 5
        System.out.println("After CLEAR bit 5: " + Integer.toBinaryString(flags));
    }
}

Output

a = 172 | 10101100 b = 63 | 111111 a & b = 44 | 101100 a | b = 191 | 10111111 a ^ b = 147 | 10010011 ~a = -173 | (32-bit two's complement) --- Bitwise Tricks --- x = 52 binary: 110100 Is even? : true x << 1 (ร—2) = 104 x >> 1 (รท2) = 26 x << 3 (ร—8) = 416 64 is power of 2? true After SET bit 3: 1000 After TOGGLE bit 3: 0 After CLEAR bit 5: 0

Decimal to Binary Conversion โ€” Step-by-Step Flow

The flowchart below illustrates the classic repeated division by 2 algorithm for converting a decimal integer to its binary representation โ€” the same algorithm used by Integer.toBinaryString() internally.

๐Ÿ“ฅ Input decimal Ne.g. N = 25
โ“ N == 0?base case check
Yes
โœ… Output '0'result is '0'
๐Ÿ“ Remainder = N mod 20 or 1 โ€” record it
โž— N = N div 2integer divide by 2
โ“ N > 0?more digits to compute?
Yes
๐Ÿ” Repeatback to compute remainder
๐Ÿ”„ Reverse remaindersread from bottom to top
โœ… Binary resulte.g. 25 โ†’ 11001

Code Execution Flow โ€” from source to output

Trace for N = 25: 25 รท 2 = 12 remainder 1 โ†’ 12 รท 2 = 6 remainder 0 โ†’ 6 รท 2 = 3 remainder 0 โ†’ 3 รท 2 = 1 remainder 1 โ†’ 1 รท 2 = 0 remainder 1. Remainders read bottom-to-top: 11001. Verify: 1ร—16 + 1ร—8 + 0ร—4 + 0ร—2 + 1ร—1 = 25 โœ“

Bit Shift Operators โ€” << >> >>>

Java's three shift operators move all bits of an integer left or right by a specified number of positions. They are equivalent to fast multiplication or division by powers of 2 and are heavily used in hashing, encoding, and performance-critical code.

โ˜• JavaShift Operators โ€” Complete Demo
public class ShiftOperators {
    public static void main(String[] args) {

        int n = 12;  // binary: 0000 1100
        System.out.println("n = " + n + "  binary: " + Integer.toBinaryString(n));

        // Left shift << : multiply by 2^k (fast power-of-2 multiplication)
        System.out.println("\n--- Left Shift (<<) ---");
        System.out.println("n << 1 = " + (n << 1) + "  (12 ร— 2 = 24)");
        System.out.println("n << 2 = " + (n << 2) + "  (12 ร— 4 = 48)");
        System.out.println("n << 3 = " + (n << 3) + "  (12 ร— 8 = 96)");

        // Signed right shift >> : divide by 2^k (preserves sign)
        System.out.println("\n--- Signed Right Shift (>>) ---");
        System.out.println("n >> 1 = " + (n >> 1) + "  (12 รท 2 = 6)");
        System.out.println("n >> 2 = " + (n >> 2) + "  (12 รท 4 = 3)");
        int neg = -48;
        System.out.println("\n-48 >> 1 = " + (neg >> 1) + "  (-48 รท 2 = -24, sign preserved)");
        System.out.println("-48 >> 2 = " + (neg >> 2) + "  (-48 รท 4 = -12, sign preserved)");

        // Unsigned right shift >>> : always fills with 0 (ignores sign)
        System.out.println("\n--- Unsigned Right Shift (>>>) ---");
        System.out.println("-48 >>> 1 = " + (-48 >>> 1) + "  (large positive โ€” sign bit โ†’ 0)");
        System.out.println("-1  >>> 1 = " + (-1 >>> 1)  + "  (Integer.MAX_VALUE = 2147483647)");

        // Real-world: HashMap's hash spreading uses >>>
        // hash(key) = key.hashCode() ^ (key.hashCode() >>> 16)
        int hashCode = 0xABCD1234;
        int spread   = hashCode ^ (hashCode >>> 16);
        System.out.printf("%nHashMap hash spread: 0x%X ^ 0x%X = 0x%X%n",
            hashCode, hashCode >>> 16, spread);

        // Mid-point without overflow โ€” used in binary search
        int lo = 1_000_000_000, hi = 2_000_000_000;
        int mid = (lo + hi) >>> 1;  // safe โ€” no overflow
        System.out.println("\nSafe mid (no overflow): " + mid);
    }
}

Output

n = 12 binary: 1100 --- Left Shift (<<) --- n << 1 = 24 (12 ร— 2 = 24) n << 2 = 48 (12 ร— 4 = 48) n << 3 = 96 (12 ร— 8 = 96) --- Signed Right Shift (>>) --- n >> 1 = 6 (12 รท 2 = 6) n >> 2 = 3 (12 รท 4 = 3) -48 >> 1 = -24 (-48 รท 2 = -24, sign preserved) -48 >> 2 = -12 (-48 รท 4 = -12, sign preserved) --- Unsigned Right Shift (>>>) --- -48 >>> 1 = 2147483624 (large positive โ€” sign bit โ†’ 0) -1 >>> 1 = 2147483647 (Integer.MAX_VALUE = 2147483647) HashMap hash spread: 0xABCD1234 ^ 0xABCD = 0xABCD9889 Safe mid (no overflow): 1500000000

Number Formatting and Display

Java's String.format() and printf() provide powerful format specifiers for displaying numbers in any base and with custom padding, making output clean and professional.

โ˜• JavaNumber Formatting with printf and String.format
public class NumberFormatting {
    public static void main(String[] args) {

        int[] values = {0, 7, 15, 42, 100, 173, 255};

        System.out.printf("%-10s %-10s %-10s %-12s%n",
            "Decimal", "Binary", "Octal", "Hexadecimal");
        System.out.println("-".repeat(45));

        for (int v : values) {
            System.out.printf("%-10d %-10s %-10o %-12X%n",
                v,
                String.format("%8s", Integer.toBinaryString(v)).replace(" ","0"),
                v,
                v);
        }

        System.out.println();

        // Format specifier summary
        int n = 255;
        System.out.println("--- Format Specifiers ---");
        System.out.printf("%d   โ†’ decimal%n",     n);
        System.out.printf("%o   โ†’ octal%n",       n);
        System.out.printf("%x   โ†’ hex lowercase%n", n);
        System.out.printf("%X   โ†’ hex uppercase%n", n);
        System.out.printf("%08X โ†’ padded hex (8 digits)%n", n);
        System.out.printf("#%06X โ†’ hex colour code%n", n);
        System.out.printf("%+d  โ†’ with sign%n",   n);
        System.out.printf("%,d  โ†’ with commas%n", 1_000_000);
        System.out.printf("%.4f โ†’ 4 decimal places%n", Math.PI);
        System.out.printf("%e   โ†’ scientific notation%n", 1234567.89);
    }
}

Output

Decimal Binary Octal Hexadecimal --------------------------------------------- 0 00000000 0 0 7 00000111 7 7 15 00001111 17 F 42 00101010 52 2A 100 01100100 144 64 173 10101101 255 AD 255 11111111 377 FF --- Format Specifiers --- 255 โ†’ decimal 377 โ†’ octal ff โ†’ hex lowercase FF โ†’ hex uppercase 000000FF โ†’ padded hex (8 digits) #0000FF โ†’ hex colour code +255 โ†’ with sign 1,000,000 โ†’ with commas 3.1416 โ†’ 4 decimal places 1.234568e+06 โ†’ scientific notation

Best Practices for Java Number Systems

Professional Java developers follow these best practices to write clear, correct, and portable code when working with number systems and bit manipulation:

  • โ–ถ

    โœ… 1. Use Binary Literals for Bit Flags and Masks โ€” When defining bit masks or flags, write them in binary (0b1000_0000) not decimal (128) or hex (0x80). Binary literals make the bit structure immediately visible without mental translation.

  • โ–ถ

    โœ… 2. Use Hex for Byte Values and Colour Codes โ€” One byte (8 bits) = two hex digits. Use 0xFF not 255 when working with byte arrays, colour components, or protocol fields. Hex communicates byte boundaries clearly.

  • โ–ถ

    โœ… 3. Use Underscore Separators for Large Literals โ€” Write 1_000_000 not 1000000, 0xFF_FF not 0xFFFF, and 0b1010_0101 not 0b10100101. Underscores dramatically improve readability for constants, bitmasks, and large numbers.

  • โ–ถ

    โœ… 4. Use >>> Instead of >> for Unsigned Operations โ€” When shifting for bit extraction or hash computation (not arithmetic division), use >>> to avoid accidental sign extension. >>> always fills with 0; >> extends the sign bit. Java's HashMap uses >>> 16 in its hash spreading โ€” not >>.

  • โ–ถ

    โœ… 5. Prefer Integer.toBinaryString() Over Manual Loops โ€” Java's built-in Integer.toBinaryString(), Integer.toHexString(), and Integer.parseInt(s, radix) are faster, tested, and handles edge cases (0, negative values) correctly. Use manual algorithms only in interviews or when custom formatting is needed.

  • โ–ถ

    โœ… 6. Be Aware of Integer Overflow in Bit Operations โ€” Left-shifting a value past the sign bit causes overflow. int max = Integer.MAX_VALUE; max << 1; wraps around. For values that might overflow, use long literals and Long arithmetic, or check bounds before shifting.

  • โ–ถ

    โœ… 7. Use EnumSet Instead of int Bitmasks for Flags in Production โ€” While int bitmasks are fast and concise, EnumSet<MyFlags> provides type safety, readable names, and efficient bit operations under the hood. Prefer EnumSet for domain flag management in production Java code.

  • โ–ถ

    โŒ 8. Never Use Octal Literals for Non-Permission Values โ€” A leading zero on an integer literal makes it octal: int x = 010 means 8, not 10! This is a notorious Java gotcha. Only use octal literals intentionally for file permission constants. Never write leading-zero decimal numbers.

Real-World Code Examples

Example 1 โ€” RGB Colour Encoder/Decoder

โ˜• JavaRGB Colour Encoder and Decoder
public class RGBColour {

    // Pack R, G, B components into a single 32-bit int
    static int encode(int r, int g, int b) {
        return (r << 16) | (g << 8) | b;
    }

    // Extract components using bit masks
    static int getRed(int colour) {
        return (colour >> 16) & 0xFF;
    }

    static int getGreen(int colour) {
        return (colour >> 8) & 0xFF;
    }

    static int getBlue(int colour) {
        return colour & 0xFF;
    }

    static String toHexCode(int colour) {
        return String.format("#%06X", colour & 0xFFFFFF);
    }

    public static void main(String[] args) {
        // Encode colours
        int tomato     = encode(255, 99, 71);
        int steelBlue  = encode(70, 130, 180);
        int gold       = encode(255, 215, 0);

        // Display colour info
        int[] colours = {tomato, steelBlue, gold};
        String[] names = {"Tomato", "SteelBlue", "Gold"};

        System.out.printf("%-12s %-10s R    G    B%n", "Name", "HexCode");
        System.out.println("-".repeat(40));
        for (int i = 0; i < colours.length; i++) {
            System.out.printf("%-12s %-10s %-4d %-4d %d%n",
                names[i],
                toHexCode(colours[i]),
                getRed(colours[i]),
                getGreen(colours[i]),
                getBlue(colours[i]));
        }

        // Decode a hex colour code
        int parsed = Integer.parseInt("4169E1", 16); // RoyalBlue
        System.out.printf("%nRoyalBlue #4169E1 โ†’ R=%d G=%d B=%d%n",
            getRed(parsed), getGreen(parsed), getBlue(parsed));
    }
}

Output

Name HexCode R G B ---------------------------------------- Tomato #FF6347 255 99 71 SteelBlue #4682B4 70 130 180 Gold #FFD700 255 215 0 RoyalBlue #4169E1 โ†’ R=65 G=105 B=225

Example 2 โ€” Permission Flags Using Bitmask

โ˜• JavaUser Permission System with Bitwise Flags
public class PermissionFlags {

    // Permission constants โ€” each is a distinct bit
    static final int READ    = 0b0001;  // bit 0 = 1
    static final int WRITE   = 0b0010;  // bit 1 = 2
    static final int EXECUTE = 0b0100;  // bit 2 = 4
    static final int DELETE  = 0b1000;  // bit 3 = 8
    static final int ADMIN   = 0b1111;  // all permissions

    // Check if a permission is set
    static boolean hasPermission(int userPerms, int flag) {
        return (userPerms & flag) != 0;
    }

    // Grant a permission
    static int grant(int userPerms, int flag) {
        return userPerms | flag;
    }

    // Revoke a permission
    static int revoke(int userPerms, int flag) {
        return userPerms & ~flag;
    }

    static void printPermissions(String user, int perms) {
        System.out.printf("%-10s [%04d] READ:%-5b WRITE:%-5b EXEC:%-5b DEL:%b%n",
            user,
            Integer.parseInt(Integer.toBinaryString(perms)),
            hasPermission(perms, READ),
            hasPermission(perms, WRITE),
            hasPermission(perms, EXECUTE),
            hasPermission(perms, DELETE));
    }

    public static void main(String[] args) {
        int arjun  = READ | WRITE;        // 0011 = 3
        int priya  = READ | EXECUTE;      // 0101 = 5
        int admin  = ADMIN;               // 1111 = 15

        System.out.println("Initial Permissions:");
        printPermissions("Arjun",  arjun);
        printPermissions("Priya",  priya);
        printPermissions("Admin",  admin);

        arjun = grant(arjun, EXECUTE);    // add execute
        priya = revoke(priya, READ);      // remove read

        System.out.println("\nAfter Updates:");
        printPermissions("Arjun",  arjun);
        printPermissions("Priya",  priya);
    }
}

Output

Initial Permissions: Arjun [0011] READ:true WRITE:true EXEC:false DEL:false Priya [0101] READ:true WRITE:false EXEC:true DEL:false Admin [1111] READ:true WRITE:true EXEC:true DEL:true After Updates: Arjun [0111] READ:true WRITE:true EXEC:true DEL:false Priya [0100] READ:false WRITE:false EXEC:true DEL:false

Practice This Code โ€” Live Editor

Advantages and Disadvantages of Working with Number Systems in Java

Understanding and using multiple number systems in Java brings concrete benefits โ€” but also requires careful handling to avoid subtle bugs.

โœ… Advantages
Native Multi-Base Literal SupportJava directly supports binary (0b), octal (0), and hexadecimal (0x) literals in source code. No conversion needed โ€” write 0xFF and Java stores it identically to 255 in memory. This makes hardware, colour, and flag constants self-documenting.
Bitwise Operations Enable High PerformanceBit manipulation (AND, OR, XOR, shifts) is the fastest category of CPU instruction โ€” no division, no branching. Checking even/odd with (n & 1), power-of-2 checks with (n & (n-1)) == 0, and bit flag operations are orders of magnitude faster than arithmetic equivalents.
Rich Integer Utility APIInteger.toBinaryString(), toHexString(), parseInt(s, radix), bitCount(), numberOfLeadingZeros() and 10+ other methods provide ready-made, tested tools for all common number-system operations without manual implementation.
Direct Hardware and Protocol CompatibilityNetwork protocols, file formats, and hardware interfaces communicate in bytes and bit fields. Binary and hex literacy lets you read and write protocol specifications directly and parse binary data formats without translation layers.
Underscore Literals Improve Code ReadabilityJava 7+ underscore separators (1_000_000, 0xFF_FF_FF, 0b1010_0101) make large constants, colour codes, and bitmasks instantly readable without magic number comments.
โŒ Disadvantages
Octal Literal Gotcha โ€” Leading ZeroA leading zero silently makes any integer literal octal: int x = 010; means x = 8, not 10. This is a notorious Java bug source. Never write decimal numbers with leading zeros โ€” use explicit octal only for permission constants where the context is unambiguous.
Signed vs Unsigned ConfusionJava has no unsigned int type (unlike C/C++). All int operations are signed two's complement. Shifting -1 >> 1 gives -1 (sign extension), not a large positive. Using >>> instead of >> for unsigned logic is non-obvious to beginners and a common bug source.
Integer Overflow Is SilentJava does not throw an exception on integer overflow โ€” it silently wraps around. Integer.MAX_VALUE + 1 gives Integer.MIN_VALUE with no warning. Left-shifting past the sign bit corrupts values silently. Overflow-safe arithmetic requires explicit checks or Math.addExact() / Math.multiplyExact().
Binary Manipulation Code Is Hard to ReadComplex bitmask expressions like (perms & ~(READ | WRITE)) | EXECUTE require careful documentation. Without clear constant names and comments, bitwise code becomes unmaintainable. Always use named constants (static final int READ = 0b0001) instead of raw literals.

Java Number System โ€” Interview Questions

These are the most frequently asked interview questions on the Java Number System and related bit manipulation for Java developer and competitive programming interviews.

Practice Questions โ€” Test Your Knowledge

Test your understanding of Java Number Systems with these practice questions. Attempt each before revealing the answer.

1. What are the decimal values of: (a) 0b1010 (b) 0777 (c) 0x1F (d) 0b1111_0000?

Easy

2. What is the output? int x = 0b1010; // 10 int y = 0b1100; // 12 System.out.println(x & y); // AND System.out.println(x | y); // OR System.out.println(x ^ y); // XOR

Easy

3. Why does int x = 09; cause a compile error but int y = 07; does not?

Easy

4. Write a Java expression to extract the lower byte (bits 0โ€“7) and upper byte (bits 8โ€“15) of an int using bitwise operators.

Medium

5. What does n & (n-1) compute? What is it useful for?

Medium

6. What is the output of Integer.toBinaryString(-5) and why does it have 32 characters?

Medium

7. A 32-bit int stores an RGBA colour as: bits 31-24 = Alpha, bits 23-16 = Red, bits 15-8 = Green, bits 7-0 = Blue. Write expressions to extract each component.

Hard

8. Without using any division operator (/) or modulo (%), determine if an integer n is even or odd using bitwise operations. Explain why it works.

Easy

Conclusion โ€” Mastering Java Number Systems

The number system is the bedrock of computer science โ€” and Java's first-class support for binary, octal, decimal, and hexadecimal literals, combined with its rich Integer utility methods and bitwise operator set, gives you every tool needed to work directly at the bit level when required.

Mastering number systems in Java means knowing when to use binary literals for bit flags, hexadecimal for byte values and colour codes, and underscore separators for readable constants. It means understanding two's complement to predict overflow behaviour, using >>> correctly for unsigned shifts, and leveraging bit tricks like n & (n-1) for high-performance operations in competitive programming and systems code.

ScenarioBest Approach
Define bit flags / permission masksโœ… Binary literals: 0b0001, 0b0010, 0b0100
Colour codes / byte values / memoryโœ… Hex literals: 0xFF, 0xCAFEBABE
Large numeric constantsโœ… Underscore separators: 1_000_000, 0xFF_FF_FF
Decimal to binary conversionโœ… Integer.toBinaryString(n) or Integer.toString(n,2)
Any base string to decimalโœ… Integer.parseInt(str, radix)
Fast multiply/divide by power of 2โœ… Left/right bit shift: n << k, n >> k
Unsigned right shiftโœ… >>> operator (not >>)
Negative binary representationโœ… Two's complement: ~n + 1
Count 1-bits in an integerโœ… Integer.bitCount(n)
Check power of 2โœ… (n > 0) && (n & (n-1)) == 0

Your next steps: explore Java's Byte and ByteBuffer classes for binary data I/O; study IEEE 754 floating-point representation to understand how float and double store fractional binary numbers; learn Java's BigInteger for arbitrary-precision arithmetic and base conversion of very large numbers; and see how bit manipulation powers Java's HashMap.hash(), UUID generation, and cryptographic operations in production systems.

Remember: Binary (0b) for flags, Hex (0x) for bytes, underscore separators for readability, >>> for unsigned shifts, and always name your bit constants. These five habits will keep your number system code correct, readable, and professional. โ˜•

Frequently Asked Questions (FAQ)