Skip to content
IRC-CodingIRC-Coding
Number systemsBinary hexadecimalBit operationsNumber conversionComputer arithmetic

Number Systems: Binary, Hex & Bit Operations

Master binary, hexadecimal, and decimal systems with practical examples, bit operations, two's complement, and computer arithmetic.

S

schutzgeist

27 min read
Number Systems: Binary, Hex & Bit Operations

Number Systems: Binary, Hexadecimal, Decimal & Bit Operations

This post is a comprehensive introduction to number systems – covering binary, hexadecimal, decimal, base conversion, and bit operations with practical examples.

In a Nutshell

Computers use binary systems (0 and 1). Hexadecimal serves as a compact representation for binary values. Bit operations enable direct manipulation of data at the bit level.

Learning Path

Beginner (Steps 1-3):

  1. Understand number system fundamentals (decimal, binary, hexadecimal)
  2. Practice simple conversions (decimal ↔ binary ↔ hex)
  3. Learn basic bit operations (AND, OR, XOR)

Intermediate (Steps 4-6): 4. Understand two’s complement and negative numbers 5. Practical applications (IP addresses, colors, MAC addresses) 6. Shift operations and bit manipulation

Advanced (Steps 7-10): 7. Advanced topics (BCD, Gray code, CRC) 8. IEEE 754 floating-point format 9. Endianness and network byte order 10. Performance optimization with bit operations

💡 Pro-Tip: Start with the interactive exercises to test your understanding!

Quick Technical Overview

Number systems are methods for representing numbers using different bases. Computers internally use the binary system (base 2), while humans prefer the decimal system (base 10).

Key number systems:

Decimal System (Base 10)

  • Digits: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9
  • Place values: 10⁰, 10¹, 10², 10³, …
  • Usage: Human communication, everyday mathematics
  • Example: 123 = 1×10² + 2×10¹ + 3×10⁰

Visual representation:

   1      2      3
  ↓      ↓      ↓
10²    10¹    10⁰
100    10     1
= 100 + 20 + 3 = 123

Binary System (Base 2)

  • Digits: 0, 1
  • Place values: 2⁰, 2¹, 2², 2³, …
  • Usage: Computer internal representation
  • Example: 1011 = 1×2³ + 0×2² + 1×2¹ + 1×2⁰ = 11

⚠️ Important: Computers work internally only with 0 and 1. All data is ultimately stored as binary numbers!

Visual representation:

   1      0      1      1
  ↓      ↓      ↓      ↓
2³     2²     2¹     2⁰
8      4      2      1
= 8 + 0 + 2 + 1 = 11

Hexadecimal System (Base 16)

  • Digits: 0-9, A, B, C, D, E, F
  • Place values: 16⁰, 16¹, 16², 16³, …
  • Usage: Compact binary representation, colors, memory addresses
  • Example: A3 = 10×16¹ + 3×16⁰ = 163

💡 Pro-Tip: 1 hex digit = 4 binary digits. Hexadecimal is perfect for representing binary since it’s more compact and readable!

Visual representation:

   A      3
  ↓      ↓
16¹    16⁰
16     1
= 160 + 3 = 163

Octal System (Base 8)

  • Digits: 0, 1, 2, 3, 4, 5, 6, 7
  • Place values: 8⁰, 8¹, 8², 8³, …
  • Usage: Historical use in Unix systems
  • Example: 75 = 7×8¹ + 5×8⁰ = 61

📜 Historical note: Octal was commonly used in early Unix systems (e.g., file permissions with chmod 755). Today, hexadecimal is more widespread.

Visual representation:

   7      5
  ↓      ↓
8¹     8⁰
8      1
= 56 + 5 = 61

Exam Essentials

  • Decimal system: Base 10, digits 0-9, place values 10ⁿ
  • Binary system: Base 2, digits 0-1, computer representation
  • Hexadecimal system: Base 16, digits 0-9, A-F, compact representation
  • Conversion: Division/multiplication by base, place value method
  • Bit operations: AND, OR, XOR, NOT, shift operations
  • Two’s complement: Negative numbers in binary
  • IHK-relevant: Foundation for computer architecture and programming

Core Components

  1. Number systems: Decimal, binary, hexadecimal, octal
  2. Conversion: Between different bases
  3. Bit operations: AND, OR, XOR, NOT, shift
  4. Two’s complement: Negative numbers
  5. Computer arithmetic: Addition, subtraction, multiplication
  6. Data types: Bits, bytes, words
  7. Memory representation: Hexadecimal addresses
  8. Error detection: Parity, checksums

Step-by-Step Conversions

💡 Pro-Tip: Practice these conversions regularly—they’re fundamental to understanding computer systems! Plus, they appear in almost every IHK AP1 or AP2 exam.

Our free online and offline calculator:

Zahlensystem-Umrechnung

Decimal to Binary (Division by 2)

Example: 13₁₀ → Binary

13 ÷ 2 = 6 remainder 1  ← least significant bit
 6 ÷ 2 = 3 remainder 0
 3 ÷ 2 = 1 remainder 1
 1 ÷ 2 = 0 remainder 1  ← most significant bit

Read from bottom to top: 1101₂

Binary to Decimal (Place Value Method)

Example: 1101₂ → Decimal

1 1 0 1
↓ ↓ ↓ ↓
2³ 2² 2¹ 2⁰
8 4 2 1

= 1×8 + 1×4 + 0×2 + 1×1
= 8 + 4 + 0 + 1
= 13₁₀

Decimal to Hexadecimal (Division by 16)

Example: 255₁₀ → Hex

255 ÷ 16 = 15 remainder 15 (F)
 15 ÷ 16 =  0 remainder 15 (F)

Read from bottom to top: FF₁₆

Hexadecimal to Binary (4-Bit Groups)

Example: A3₁₆ → Binary

A (10)      3
↓           ↓
1010        0011

Combined: 10100011₂

Binary to Hexadecimal (4-Bit Groups)

Example: 10100011₂ → Hex

1010 0011
↓     ↓
A     3

Combined: A3₁₆

Practical Examples

1. Converting Between Number Systems

public class NumberSystemConversion {
    
    // Decimal to binary
    public static String decimalToBinary(int decimal) {
        if (decimal == 0) return "0";
        
        StringBuilder binary = new StringBuilder();
        while (decimal > 0) {
            binary.append(decimal % 2);
            decimal /= 2;
        }
        return binary.reverse().toString();
    }
    
    // Binary to decimal
    public static int binaryToDecimal(String binary) {
        int decimal = 0;
        int power = 0;
        
        for (int i = binary.length() - 1; i >= 0; i--) {
            if (binary.charAt(i) == '1') {
                decimal += Math.pow(2, power);
            }
            power++;
        }
        return decimal;
    }
    
    // Decimal to hexadecimal
    public static String decimalToHex(int decimal) {
        if (decimal == 0) return "0";
        
        char[] hexDigits = {'0', '1', '2', '3', '4', '5', '6', '7', 
                           '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
        StringBuilder hex = new StringBuilder();
        
        while (decimal > 0) {
            int remainder = decimal % 16;
            hex.append(hexDigits[remainder]);
            decimal /= 16;
        }
        return hex.reverse().toString();
    }
    
    // Hexadecimal to decimal
    public static int hexToDecimal(String hex) {
        int decimal = 0;
        String hexDigits = "0123456789ABCDEF";
        
        for (int i = 0; i < hex.length(); i++) {
            char digit = hex.charAt(i);
            int value = hexDigits.indexOf(digit);
            decimal = decimal * 16 + value;
        }
        return decimal;
    }
    
    // Binary to hexadecimal
    public static String binaryToHex(String binary) {
        // Pad binary to multiple of 4
        while (binary.length() % 4 != 0) {
            binary = "0" + binary;
        }
        
        StringBuilder hex = new StringBuilder();
        for (int i = 0; i < binary.length(); i += 4) {
            String nibble = binary.substring(i, i + 4);
            int value = binaryToDecimal(nibble);
            hex.append(decimalToHex(value));
        }
        return hex.toString();
    }
    
    // Hexadecimal to binary
    public static String hexToBinary(String hex) {
        String[] binaryMap = {
            "0000", "0001", "0010", "0011",
            "0100", "0101", "0110", "0111",
            "1000", "1001", "1010", "1011",
            "1100", "1101", "1110", "1111"
        };
        
        StringBuilder binary = new StringBuilder();
        for (int i = 0; i < hex.length(); i++) {
            char digit = hex.charAt(i);
            int value = "0123456789ABCDEF".indexOf(digit);
            binary.append(binaryMap[value]);
        }
        
        // Remove leading zeros
        while (binary.length() > 1 && binary.charAt(0) == '0') {
            binary.deleteCharAt(0);
        }
        
        return binary.toString();
    }
    
    public static void main(String[] args) {
        int number = 175;
        
        System.out.println("Number: " + number);
        System.out.println("Binary: " + decimalToBinary(number));
        System.out.println("Hex: " + decimalToHex(number));
        
        String binary = "10101111";
        String hex = "AF";
        
        System.out.println("\nBinary " + binary + " = Decimal " + binaryToDecimal(binary));
        System.out.println("Hex " + hex + " = Decimal " + hexToDecimal(hex));
        System.out.println("Binary " + binary + " = Hex " + binaryToHex(binary));
        System.out.println("Hex " + hex + " = Binary " + hexToBinary(hex));
    }
}

2. Bit Operations Across Languages

// Java Bit Operations
public class BitOperationen {
    
    public static void main(String[] args) {
        int a = 12;  // 1100 in binary
        int b = 10;  // 1010 in binary
        
        System.out.println("a = " + a + " (Binary: " + Integer.toBinaryString(a) + ")");
        System.out.println("b = " + b + " (Binary: " + Integer.toBinaryString(b) + ")");
        
        // Bitwise AND (&)
        int and = a & b;  // 1100 & 1010 = 1000 (8)
        System.out.println("a & b = " + and + " (Binary: " + Integer.toBinaryString(and) + ")");
        
        // Bitwise OR (|)
        int or = a | b;   // 1100 | 1010 = 1110 (14)
        System.out.println("a | b = " + or + " (Binary: " + Integer.toBinaryString(or) + ")");
        
        // Bitwise XOR (^)
        int xor = a ^ b;  // 1100 ^ 1010 = 0110 (6)
        System.out.println("a ^ b = " + xor + " (Binary: " + Integer.toBinaryString(xor) + ")");
        
        // Bitwise NOT (~)
        int notA = ~a;   // ~1100 = 0011 (using two's complement)
        System.out.println("~a = " + notA + " (Binary: " + Integer.toBinaryString(notA) + ")");
        
        // Left Shift (<<)
        int leftShift = a << 2;  // 1100 << 2 = 110000 (48)
        System.out.println("a << 2 = " + leftShift + " (Binary: " + Integer.toBinaryString(leftShift) + ")");
        
        // Right Shift (>>)
        int rightShift = a >> 1;  // 1100 >> 1 = 0110 (6)
        System.out.println("a >> 1 = " + rightShift + " (Binary: " + Integer.toBinaryString(rightShift) + ")");
        
        // Unsigned Right Shift (>>>)
        int unsignedRightShift = a >>> 1;  // 1100 >>> 1 = 0110 (6)
        System.out.println("a >>> 1 = " + unsignedRightShift + " (Binary: " + Integer.toBinaryString(unsignedRightShift) + ")");
        
        // Practical applications
        praktischeAnwendungen();
    }
    
    private static void praktischeAnwendungen() {
        System.out.println("\n=== Practical Applications ===");
        
        // Check if a bit is set (is the 3rd bit set?)
        int zahl = 12;  // 1100
        int bitPosition = 2;
        boolean bitSet = (zahl & (1 << bitPosition)) != 0;
        System.out.println("Bit " + bitPosition + " in " + zahl + " is set: " + bitSet);
        
        // Set a bit
        int mitBit = zahl | (1 << bitPosition);
        System.out.println("Set bit " + bitPosition + ": " + mitBit);
        
        // Clear a bit
        int ohneBit = zahl & ~(1 << bitPosition);
        System.out.println("Clear bit " + bitPosition + ": " + ohneBit);
        
        // Toggle a bit
        int umgeschaltet = zahl ^ (1 << bitPosition);
        System.out.println("Toggle bit " + bitPosition + ": " + umgeschaltet);
        
        // Extract color from RGB values
        int farbe = 0xFF6B35;  // Orange
        int rot = (farbe >> 16) & 0xFF;
        int gruen = (farbe >> 8) & 0xFF;
        int blau = farbe & 0xFF;
        
        System.out.println("\nColor: #" + Integer.toHexString(farbe).toUpperCase());
        System.out.println("Red: " + rot);
        System.out.println("Green: " + gruen);
        System.out.println("Blue: " + blau);
    }
}

3. Two’s Complement for Negative Numbers

⚠️ Important: Two’s complement is the standard for negative numbers in modern computers. Avoid one’s complement and sign-magnitude representation!

public class Zweierkomplement {
    
    // Calculate two's complement
    public static String zweierkomplement(int zahl, int bits) {
        if (zahl >= 0) {
            return String.format("%" + bits + "s", Integer.toBinaryString(zahl)).replace(' ', '0');
        }
        
        // Negative number: 2^bits + zahl
        int positiv = (int) (Math.pow(2, bits) + zahl);
        return String.format("%" + bits + "s", Integer.toBinaryString(positiv)).replace(' ', '0');
    }
    
    // Convert from two's complement to decimal
    public static int vonZweierkomplement(String binaer) {
        int bits = binaer.length();
        
        // If the highest bit is 0, it's a positive number
        if (binaer.charAt(0) == '0') {
            return Integer.parseInt(binaer, 2);
        }
        
        // Negative number: - (2^bits - value)
        int wert = Integer.parseInt(binaer, 2);
        return wert - (int) Math.pow(2, bits);
    }
    
    public static void main(String[] args) {
        int[] zahlen = {13, 5, 0, -1, -5, -13};
        int bits = 8;
        
        System.out.println("Two's complement with " + bits + " bits:");
        System.out.println("Number\tBinary\t\tDecimal");
        System.out.println("------\t------\t\t-------");
        
        for (int zahl : zahlen) {
            String binaer = zweierkomplement(zahl, bits);
            System.out.println(zahl + "\t" + binaer + "\t" + vonZweierkomplement(binaer));
        }
        
        // Show range
        System.out.println("\nRange with " + bits + " bits:");
        System.out.println("Minimum: " + (-(int) Math.pow(2, bits-1)));
        System.out.println("Maximum: " + ((int) Math.pow(2, bits-1) - 1));
        
        // Demonstrate overflow
        System.out.println("\nOverflow demonstration:");
        int max = (int) Math.pow(2, bits-1) - 1;
        int ueberlauf = max + 1;
        
        System.out.println("Max: " + max + " -> " + zweierkomplement(max, bits));
        System.out.println("Max+1: " + ueberlauf + " -> " + zweierkomplement(ueberlauf, bits));
        System.out.println("Expected: " + (-(int) Math.pow(2, bits-1)) + " -> " + zweierkomplement(-(int) Math.pow(2, bits-1), bits));
    }
}

4. Computer Arithmetic

⚠️ Warning: Binary arithmetic can lead to overflows. Always check the range limits of your data types!

public class Computerarithmetik {
    
    // Binary addition
    public static String binaerAddition(String a, String b) {
        int laenge = Math.max(a.length(), b.length());
        
        // Pad with leading zeros
        a = String.format("%" + laenge + "s", a).replace(' ', '0');
        b = String.format("%" + laenge + "s", b).replace(' ', '0');
        
        StringBuilder ergebnis = new StringBuilder();
        int carry = 0;
        
        // Add from right to left
        for (int i = laenge - 1; i >= 0; i--) {
            int summe = carry + (a.charAt(i) - '0') + (b.charAt(i) - '0');
            ergebnis.append(summe % 2);
            carry = summe / 2;
        }
        
        // Add final carry if needed
        if (carry > 0) {
            ergebnis.append(carry);
        }
        
        return ergebnis.reverse().toString();
    }
    
    // Binary subtraction (using two's complement method)
    public static String binaerSubtraktion(String a, String b) {
        // Negate b (two's complement)
        String negiert = zweierkomplementNegieren(b);
        
        // a + (-b)
        return binaerAddition(a, negiert);
    }
    
    private static String zweierkomplementNegieren(String binaer) {
        // Invert bits
        StringBuilder invertiert = new StringBuilder();
        for (char bit : binaer.toCharArray()) {
            invertiert.append(bit == '0' ? '1' : '0');
        }
        
        // Add 1
        return binaerAddition(invertiert.toString(), "1");
    }
    
    // Binary multiplication
    public static String binaerMultiplikation(String a, String b) {
        int aDez = Integer.parseInt(a, 2);
        int bDez = Integer.parseInt(b, 2);
        int produkt = aDez * bDez;
        
        return Integer.toBinaryString(produkt);
    }
    
    // Fixed-point arithmetic
    public static double festePunktAddition(double a, double b, int nachkommastellen) {
        int faktor = (int) Math.pow(10, nachkommastellen);
        int aInt = (int) Math.round(a * faktor);
        int bInt = (int) Math.round(b * faktor);
        int ergebnisInt = aInt + bInt;
        
        return (double) ergebnisInt / faktor;
    }
    
    // Floating-point representation (simplified)
    public static void gleitkommaDarstellung(double zahl) {
        if (zahl == 0) {
            System.out.println("0 = 0.0 × 2^0");
            return;
        }
        
        boolean negativ = zahl < 0;
        zahl = Math.abs(zahl);
        
        int exponent = 0;
        
        // Normalize
        while (zahl >= 2.0) {
            zahl /= 2.0;
            exponent++;
        }
        
        while (zahl < 1.0) {
            zahl *= 2.0;
            exponent--;
        }
        
        System.out.println((negativ ? "-" : "") + zahl + " × 2^" + exponent);
    }
    
    public static void main(String[] args) {
        System.out.println("=== Binary Arithmetic ===");
        
        String a = "1011";  // 11
        String b = "1101";  // 13
        
        System.out.println("a = " + a + " (" + Integer.parseInt(a, 2) + ")");
        System.out.println("b = " + b + " (" + Integer.parseInt(b, 2) + ")");
        
        String summe = binaerAddition(a, b);
        System.out.println("a + b = " + summe + " (" + Integer.parseInt(summe, 2) + ")");
        
        String differenz = binaerSubtraktion(b, a);
        System.out.println("b - a = " + differenz + " (" + Integer.parseInt(differenz, 2) + ")");
        
        String produkt = binaerMultiplikation(a, b);
        System.out.println("a × b = " + produkt + " (" + Integer.parseInt(produkt, 2) + ")");
        
        System.out.println("\n=== Fixed-Point Arithmetic ===");
        double x = 12.34;
        double y = 5.67;
        double summeFP = festePunktAddition(x, y, 2);
        System.out.println(x + " + " + y + " = " + summeFP + " (2 decimal places)");
        
        System.out.println("\n=== Floating-Point Representation ===");
        double[] zahlen = {12.5, 0.75, -3.125, 256.0};
        for (double zahl : zahlen) {
            System.out.print(zahl + " = ");
            gleitkommaDarstellung(zahl);
        }
    }
}

5. Python Bit Operations and Number Systems

# Python number systems and bit operations

def decimal_to_binary(decimal):
    """Convert decimal to binary"""
    if decimal == 0:
        return "0"
    
    binary = ""
    while decimal > 0:
        binary = str(decimal % 2) + binary
        decimal //= 2
    
    return binary

def binary_to_decimal(binary):
    """Convert binary to decimal"""
    return int(binary, 2)

def decimal_to_hex(decimal):
    """Convert decimal to hexadecimal"""
    hex_digits = "0123456789ABCDEF"
    
    if decimal == 0:
        return "0"
    
    hex = ""
    while decimal > 0:
        hex = hex_digits[decimal % 16] + hex
        decimal //= 16
    
    return hex

def hex_to_decimal(hex):
    """Convert hexadecimal to decimal"""
    return int(hex, 16)

def bit_operations_demo():
    """Demonstrate bit operations"""
    a = 12  # 1100
    b = 10  # 1010
    
    print(f"a = {a} (Binary: {bin(a)})")
    print(f"b = {b} (Binary: {bin(b)})")
    
    # Bitwise AND
    and_result = a & b
    print(f"a & b = {and_result} (Binary: {bin(and_result)})")
    
    # Bitwise OR
    or_result = a | b
    print(f"a | b = {or_result} (Binary: {bin(or_result)})")
    
    # Bitwise XOR
    xor_result = a ^ b
    print(f"a ^ b = {xor_result} (Binary: {bin(xor_result)})")
    
    # Bitwise NOT
    not_a = ~a
    print(f"~a = {not_a} (Binary: {bin(not_a & 0xFFFFFFFF)})")
    
    # Left Shift
    left_shift = a << 2
    print(f"a << 2 = {left_shift} (Binary: {bin(left_shift)})")
    
    # Right Shift
    right_shift = a >> 1
    print(f"a >> 1 = {right_shift} (Binary: {bin(right_shift)})")

def color_from_rgb(red, green, blue):
    """Pack RGB color as 24-bit value"""
    return (red << 16) | (green << 8) | blue

def rgb_from_color(color):
    """Extract RGB components from 24-bit color"""
    red = (color >> 16) & 0xFF
    green = (color >> 8) & 0xFF
    blue = color & 0xFF
    return red, green, blue

def bit_manipulation_demo():
    """Demonstrate bit manipulation"""
    number = 0b10101000  # 168
    
    print(f"Original number: {number} (Binary: {bin(number)})")
    
    # Check bit
    bit_position = 3
    bit_set = (number & (1 << bit_position)) != 0
    print(f"Bit {bit_position} set: {bit_set}")
    
    # Set bit
    with_bit = number | (1 << bit_position)
    print(f"Set bit {bit_position}: {with_bit} (Binary: {bin(with_bit)})")
    
    # Clear bit
    without_bit = number & ~(1 << bit_position)
    print(f"Clear bit {bit_position}: {without_bit} (Binary: {bin(without_bit)})")
    
    # Toggle bit
    toggled = number ^ (1 << bit_position)
    print(f"Toggle bit {bit_position}: {toggled} (Binary: {bin(toggled)})")

def main():
    """Main program with all demonstrations"""
    print("=== Number System Conversions ===")
    
    number = 175
    print(f"Decimal {number}:")
    print(f"  Binary: {decimal_to_binary(number)}")
    print(f"  Hex: {decimal_to_hex(number)}")
    
    print("\n=== Bit Operations ===")
    bit_operations_demo()
    
    print("\n=== Bit Manipulation ===")
    bit_manipulation_demo()
    
    print("\n=== Colors as RGB ===")
    orange = color_from_rgb(255, 107, 53)
    print(f"Orange: #{orange:06X}")
    
    r, g, b = rgb_from_color(orange)
    print(f"RGB: ({r}, {g}, {b})")
    
    print("\n=== Two's Complement (8-Bit) ===")
    for i in range(-5, 6):
        if i >= 0:
            binary = format(i, '08b')
        else:
            binary = format((256 + i), '08b')
        print(f"{i:3d}: {binary}")

if __name__ == "__main__":
    main()

Real-World Examples

1. IP Addresses (IPv4)

IPv4 addresses consist of 4 bytes (32 bits), typically written in decimal notation:

Example: 192.168.1.1

192      168      1       1
↓        ↓        ↓       ↓
11000000 10101000 00000001 00000001
C0       A8       01      01 (Hex)

Binary: 11000000101010000000000100000001
Hex:   C0A80101

Subnet Mask Example: 255.255.255.0

255      255      255     0
↓        ↓        ↓       ↓
11111111 11111111 11111111 00000000
FF       FF       FF      00 (Hex)

2. MAC Addresses

MAC addresses are 6 bytes (48 bits), typically written in hexadecimal notation:

Example: 00:1A:2B:3C:4D:5E

00:1A:2B:3C:4D:5E
↓  ↓  ↓  ↓  ↓  ↓
00000000:00011010:00101011:00111100:01001101:01011110

Manufacturer (OUI): 00:1A:2B
Device ID: 3C:4D:5E

3. Unicode and UTF-8

Unicode characters are represented as code points, and UTF-8 encodes these into bytes:

Example: ‘A’ (U+0041)

Unicode: U+0041
Decimal: 65
Binary:  01000001
UTF-8:   01000001 (1 byte)

Example: ’€’ (U+20AC)

Unicode: U+20AC
Decimal: 8364
Binary:  00100000 10101100
UTF-8:   11100010 10000011 10101100 (3 bytes)
Hex:     E2 82 AC

4. Color Codes (RGB)

Web colors are represented as 24-bit hexadecimal values:

Example: #FF6B35 (Orange)

#FF6B35
↓↓↓↓↓↓
Red   Green Blue
FF     6B    35
↓      ↓     ↓
255    107   53

Binary: 11111111 01101011 00110101

Java Example:

int orange = 0xFF6B35;
int red = (orange >> 16) & 0xFF;   // 255
int green = (orange >> 8) & 0xFF;   // 107
int blue = orange & 0xFF;            // 53

5. File Sizes (Binary vs. Decimal)

Binary Prefixes (IEC 80000-13):

1 KiB = 2¹⁰ = 1,024 bytes
1 MiB = 2²⁰ = 1,048,576 bytes
1 GiB = 2³⁰ = 1,073,741,824 bytes

Decimal Prefixes (SI):

1 KB = 10³ = 1,000 bytes
1 MB = 10⁶ = 1,000,000 bytes
1 GB = 10⁹ = 1,000,000,000 bytes

Example: 1 GB Hard Drive

Manufacturer (decimal): 1,000,000,000 bytes
Operating system (binary): 1,000,000,000 ÷ 1,073,741,824 = 0.93 GB

6. ASCII Table (Selection)

CharacterDecimalHexBinary
A654101000001
B664201000010
C674301000011
a976101100001
b986201100010
c996301100011
0483000110000
9573900111001

Interactive Exercises

Conversion Exercises

Exercise 1: Decimal to Binary Convert the following decimal numbers to binary:

  • 42
  • 127
  • 255
Show solutions
42₁₀ = 101010₂
127₁₀ = 1111111₂
255₁₀ = 11111111₂

Exercise 2: Binary to Decimal Convert the following binary numbers to decimal:

  • 10101
  • 11110000
  • 10000000
Show solutions
10101₂ = 21₁₀
11110000₂ = 240₁₀
10000000₂ = 128₁₀

Exercise 3: Decimal to Hexadecimal Convert the following decimal numbers to hexadecimal:

  • 100
  • 255
  • 4095
Show solutions
100₁₀ = 64₁₆
255₁₀ = FF₁₆
4095₁₀ = FFF₁₆

Exercise 4: Hexadecimal to Binary Convert the following hexadecimal numbers to binary:

  • A5
  • FF
  • 1B
Show solutions
A5₁₆ = 10100101₂
FF₁₆ = 11111111₂
1B₁₆ = 00011011₂

Bit Operations Quiz

Question 1: What is the result of 12 & 10?

Show solution
12₁₀ = 1100₂
10₁₀ = 1010₂
1100 & 1010 = 1000₂ = 8₁₀

Question 2: What is the result of 12 | 10?

Show solution
12₁₀ = 1100₂
10₁₀ = 1010₂
1100 | 1010 = 1110₂ = 14₁₀

Question 3: What is the result of 12 ^ 10?

Show solution
12₁₀ = 1100₂
10₁₀ = 1010₂
1100 ^ 1010 = 0110₂ = 6₁₀

Question 4: What is the result of 8 << 2?

Show solution
8₁₀ = 1000₂
1000 << 2 = 100000₂ = 32₁₀

Question 5: What is the result of 16 >> 2?

Show solution
16₁₀ = 10000₂
10000 >> 2 = 100₂ = 4₁₀

Challenge Exercises

Exercise 6: Bit Manipulation Given the number 42 (101010₂). Set the 3rd bit (from the right, 0-indexed).

Show Solution
42 = 101010₂
3rd bit from right = bit position 2
42 | (1 << 2) = 42 | 4 = 46₁₀ = 101110₂

Exercise 7: Two’s Complement Represent -5 in 8-bit two’s complement.

Show Solution
5₁₀ = 00000101₂
Invert: 11111010₂
+ 1:    11111011₂

-5₁₀ = 11111011₂ (8-bit two's complement)

Exercise 8: IP Address Convert the IP address 10.0.0.1 to hexadecimal.

Show Solution
10.0.0.1
↓ ↓ ↓ ↓
0A 00 00 01

Hex: 0A000001

Common Pitfalls and Mistakes

1. Off-by-one Errors in Bit Positions

Problem: Bit positions are frequently miscounted (0-indexed vs. 1-indexed)

// ❌ Wrong: Bit position 3 is the 4th bit from the right
int bitPosition = 3;
boolean bitSet = (zahl & (1 << bitPosition)) != 0; // Checks bit 3 (4th bit)

// ✅ Correct: Document the indexing clearly
// Bit position 0 = rightmost bit (LSB)
// Bit position 7 = leftmost bit in 8-bit
int bitPosition = 2; // 3rd bit from right (0-indexed)
boolean bitSet = (zahl & (1 << bitPosition)) != 0;

2. Sign Handling During Shifts

Problem: Right-shift behaves differently for signed vs. unsigned integers

// Java: Signed right shift (>>) fills with sign bit
int x = -8; // 11111111111111111111111111111000
int result = x >> 2; // 11111111111111111111111111111110 (-2)

// Unsigned right shift (>>>) fills with 0
int x = -8;
int result = x >>> 2; // 00111111111111111111111111111110 (1073741822)

3. Overflow Issues

Problem: Integer overflow often goes unnoticed

// ❌ No overflow check
int max = Integer.MAX_VALUE; // 2147483647
int overflow = max + 1;      // -2147483648 (overflow!)

// ✅ With overflow check
if (max == Integer.MAX_VALUE) {
    throw new ArithmeticException("Integer overflow");
}

4. Misunderstanding Hex Conventions

Problem: Different notations exist for hexadecimal numbers

// Various conventions:
0xFF      // Java/C prefix
0xFF      // C# prefix
0xFF      // JavaScript prefix
#FF       // CSS/Web
FFh       // Assembler
$FF       // Pascal

5. Forgetting Endianness

Problem: Byte order is often overlooked

// Little endian (x86, ARM): least significant byte first
int value = 0x12345678;
// In memory: 78 56 34 12

// Big endian (network, PowerPC): most significant byte first
// In memory: 12 34 56 78

// Conversion:
int littleEndian = 0x12345678;
int bigEndian = Integer.reverseBytes(littleEndian); // 0x78563412

6. Incorrect Radix in parseInt

Problem: The radix is not specified correctly

// ❌ Wrong: Decimal instead of binary
int value = Integer.parseInt("1010"); // 1010 (decimal)

// ✅ Correct: Specify the radix
int value = Integer.parseInt("1010", 2); // 10 (decimal)
int hexValue = Integer.parseInt("FF", 16); // 255 (decimal)

7. Exceeding Two’s Complement Range

Problem: Number doesn’t fit within the specified bit width

// 8-bit two's complement: -128 to 127
int value = 200; // ❌ Exceeds range!

// Range check:
if (value < -128 || value > 127) {
    throw new IllegalArgumentException("Value outside 8-bit range");
}

8. Float vs. Integer Division

Problem: Integer division truncates decimal places

// ❌ Wrong: Integer division
int result = 5 / 2; // 2 (instead of 2.5)

// ✅ Correct: Float division
double result = 5.0 / 2.0; // 2.5

9. Negation vs. Complement

Problem: Confusing logical negation with bitwise complement

// Logical NOT (!)
boolean a = true;
boolean b = !a; // false

// Bitwise NOT (~)
int x = 5;      // 0101
int y = ~x;     // 1010 (with two's complement: -6)

10. Leading Zeros in Hex

Problem: Leading zeros can change meaning in certain contexts

// In Java: 0x0F = 15, 0xF = 15 (same)
// But in string comparisons:
String a = "0F";
String b = "F";
// a.equals(b) = false!

Practical Tips for Developers

1. Debugging with Binary/Hex View

Leverage IDE tools:

// IntelliJ/Eclipse: Binary view in debugger
// Variable: 175
// Binary: 10101111
// Hex:    AF

Log values in different bases:

System.out.println("Decimal: " + zahl);
System.out.println("Binary: " + Integer.toBinaryString(zahl));
System.out.println("Hex: " + Integer.toHexString(zahl));
System.out.println("Octal: " + Integer.toOctalString(zahl));

2. Bit Flags in APIs

Efficient status flags:

// Define flag constants
public static final int READ = 1 << 0;   // 0001
public static final int WRITE = 1 << 1;  // 0010
public static final int EXECUTE = 1 << 2; // 0100

// Combine flags
int permissions = READ | WRITE; // 0011

// Check flags
boolean canRead = (permissions & READ) != 0;
boolean canWrite = (permissions & WRITE) != 0;
boolean canExecute = (permissions & EXECUTE) != 0;

3. Performance Benefits of Bit Operations

Multiplication/division via shifts:

// Faster than * 2
int x = 5;
int doubled = x << 1; // 10

// Faster than / 2
int halved = x >> 1; // 2

// Modulo 2^n with AND
int modulo8 = x & 0x7; // x % 8

⚠️ Note: Modern compilers often optimize automatically—use bit shifts only in performance-critical code.

4. Manipulating Color Values

Process RGB colors efficiently:

// Create color
int color = (255 << 16) | (107 << 8) | 53; // #FF6B35

// Extract components
int red = (color >> 16) & 0xFF;
int green = (color >> 8) & 0xFF;
int blue = color & 0xFF;

// Manipulate color
int newColor = color & 0x00FFFFFF; // Clear red component
newColor |= (200 << 16); // Set new red value

5. Network Byte Order

Ensure portability:

// Host to network short (16-bit)
short hostPort = 8080;
short networkPort = Short.reverseBytes(hostPort);

// Network to host long (32-bit)
int networkAddress = 0xC0A80101; // 192.168.1.1
int hostAddress = Integer.reverseBytes(networkAddress);

6. Bitmasks for Configuration

Store configuration compactly:

public class Config {
    private int flags = 0;
    
    public static final int DEBUG = 1 << 0;
    public static final int VERBOSE = 1 << 1;
    public static final int LOGGING = 1 << 2;
    
    public void setFlag(int flag) {
        flags |= flag;
    }
    
    public void clearFlag(int flag) {
        flags &= ~flag;
    }
    
    public boolean hasFlag(int flag) {
        return (flags & flag) != 0;
    }
}

7. Memory-Efficient Data Structures

Use bits for boolean values:

// Instead of 8 booleans (8 bytes):
// boolean[] flags = new boolean[8];

// One int (4 bytes) for 8 flags:
int flags = 0;
flags |= (1 << 3); // Set 3rd flag

8. Hash Functions with Bit Operations

Simple hash function:

public static int simpleHash(String s) {
    int hash = 0;
    for (int i = 0; i < s.length(); i++) {
        hash = (hash << 5) - hash + s.charAt(i);
    }
    return hash;
}

9. Parity Calculation

Parity bit for error detection:

public static boolean calculateParity(int x) {
    boolean parity = false;
    while (x != 0) {
        parity = !parity;
        x = x & (x - 1); // Clears the lowest set bit
    }
    return parity;
}

10. Power-of-2 Check

Efficient test for powers of two:

public static boolean isPowerOfTwo(int x) {
    return x > 0 && (x & (x - 1)) == 0;
}

// Examples:
// isPowerOfTwo(1) = true  (2⁰)
// isPowerOfTwo(2) = true  (2¹)
// isPowerOfTwo(4) = true  (2²)
// isPowerOfTwo(8) = true  (2³)
// isPowerOfTwo(6) = false

Advanced Topics

1. BCD (Binary Coded Decimal)

BCD encodes each decimal digit in 4 bits:

Example: 42 in BCD

4      2
↓      ↓
0100   0010

BCD: 01000010

Advantages:

  • Simple conversion to and from decimal
  • Precise decimal arithmetic

Disadvantages:

  • Inefficient storage (6 out of 16 values unused)
  • More complex arithmetic

Java implementation:

public class BCD {
    public static int decimalToBCD(int decimal) {
        int bcd = 0;
        int shift = 0;
        
        while (decimal > 0) {
            int digit = decimal % 10;
            bcd |= (digit << shift);
            decimal /= 10;
            shift += 4;
        }
        
        return bcd;
    }
    
    public static int bcdToDecimal(int bcd) {
        int decimal = 0;
        int multiplier = 1;
        
        while (bcd > 0) {
            int digit = bcd & 0xF;
            decimal += digit * multiplier;
            bcd >>= 4;
            multiplier *= 10;
        }
        
        return decimal;
    }
}

2. Gray Code

Gray Code is a binary numeral system where consecutive values differ by only one bit:

Gray Code Table (4 bit):

Decimal | Binary | Gray Code
--------|--------|----------
0       | 0000   | 0000
1       | 0001   | 0001
2       | 0010   | 0011
3       | 0011   | 0010
4       | 0100   | 0110
5       | 0101   | 0111
6       | 0110   | 0101
7       | 0111   | 0100

Binary to Gray Code:

public static int binaryToGray(int binary) {
    return binary ^ (binary >> 1);
}

Gray Code to Binary:

public static int grayToBinary(int gray) {
    int binary = gray;
    while (gray > 0) {
        gray >>= 1;
        binary ^= gray;
    }
    return binary;
}

Applications: Rotary encoders, error minimization in switches

3. CRC (Cyclic Redundancy Check)

CRC is an error detection method for data transmission:

Simple CRC-8 implementation:

public class CRC8 {
    private static final int POLYNOMIAL = 0x07;
    
    public static int calculate(byte[] data) {
        int crc = 0x00;
        
        for (byte b : data) {
            crc ^= b;
            
            for (int i = 0; i < 8; i++) {
                if ((crc & 0x80) != 0) {
                    crc = (crc << 1) ^ POLYNOMIAL;
                } else {
                    crc <<= 1;
                }
            }
        }
        
        return crc & 0xFF;
    }
}

Used in:

  • Network protocols (Ethernet, USB)
  • File integrity checking
  • Memory error detection

4. IEEE 754 Floating Point Format

Standard representation for floating-point numbers:

32-Bit Single Precision:

Bit 31:     Sign (S)
Bits 30-23: Exponent (E, 8 bit)
Bits 22-0:  Mantissa (M, 23 bit)

Value = (-1)^S × 2^(E-127) × (1 + M)

Example: 12.5 in IEEE 754

12.5 = 1100.1₂ = 1.1001₂ × 2³

S = 0 (positive)
E = 127 + 3 = 130 = 10000010₂
M = 10010000000000000000000

IEEE 754: 01000001010010000000000000000000
Hex:      41480000

Java implementation:

public class IEEE754 {
    public static String floatToBits(float value) {
        int bits = Float.floatToIntBits(value);
        return String.format("%32s", Integer.toBinaryString(bits))
                       .replace(' ', '0');
    }
    
    public static float bitsToFloat(String bits) {
        int intValue = Integer.parseInt(bits, 2);
        return Float.intBitsToFloat(intValue);
    }
}

5. Endianness (Byte Order)

Big Endian: Most significant byte first (Network Byte Order) Little Endian: Least significant byte first (x86, ARM)

Example: 0x12345678

Big Endian:    12 34 56 78
Little Endian: 78 56 34 12

Conversion in Java:

public class Endianness {
    // Little Endian to Big Endian
    public static int littleToBig(int value) {
        return Integer.reverseBytes(value);
    }
    
    // Big Endian to Little Endian
    public static int bigToLittle(int value) {
        return Integer.reverseBytes(value);
    }
    
    // Check system endianness
    public static boolean isLittleEndian() {
        int test = 0x12345678;
        byte[] bytes = new byte[] {
            (byte) (test >> 24),
            (byte) (test >> 16),
            (byte) (test >> 8),
            (byte) test
        };
        return bytes[0] == 0x78; // Little Endian
    }
}

Critical for:

  • Network protocols (TCP/IP uses Big Endian)
  • File formats
  • Cross-platform development

6. Parity Bit

A simple error detection technique:

Even Parity:

Data: 1011
Parity: 0 (to make the count of 1s even: 10110 → 3 ones = odd ❌)
Parity: 1 (to make the count of 1s even: 10111 → 4 ones = even ✅)

Java implementation:

public class Parity {
    public static boolean calculateEvenParity(byte data) {
        int count = Integer.bitCount(data & 0xFF);
        return (count % 2) == 0;
    }
    
    public static byte setEvenParity(byte data) {
        if (calculateEvenParity(data)) {
            return (byte) (data & 0x7F); // Parity bit = 0
        } else {
            return (byte) (data | 0x80); // Parity bit = 1
        }
    }
}

7. Checksums

Simple checksums for data integrity:

Simple Checksum:

public class Checksum {
    public static int calculate(byte[] data) {
        int sum = 0;
        for (byte b : data) {
            sum += (b & 0xFF);
        }
        return sum & 0xFFFF; // 16-bit checksum
    }
    
    public static boolean verify(byte[] data, int checksum) {
        return calculate(data) == checksum;
    }
}

8. Base64 Encoding

Encode binary data as ASCII characters:

Example:

Binary: 01000001 01000010 01000011 (ABC)
Base64: QUJD

Java implementation:

import java.util.Base64;

public class Base64Example {
    public static String encode(String input) {
        return Base64.getEncoder().encodeToString(input.getBytes());
    }
    
    public static String decode(String encoded) {
        byte[] decoded = Base64.getDecoder().decode(encoded);
        return new String(decoded);
    }
}

9. Bit Rotation

Rotation without losing bits:

Left Rotation:

public static int rotateLeft(int value, int shift) {
    return (value << shift) | (value >>> (32 - shift));
}

Right Rotation:

public static int rotateRight(int value, int shift) {
    return (value >>> shift) | (value << (32 - shift));
}

Example:

int x = 0b11000000; // 192
int rotated = rotateLeft(x, 2); // 0b00000011 (3)

10. Hamming Distance

The count of differing bits between two values:

public static int hammingDistance(int a, int b) {
    int xor = a ^ b;
    return Integer.bitCount(xor);
}

// Example:
// hammingDistance(0b1010, 0b1100) = 2
// 1010 ^ 1100 = 0110 (2 ones)

Use cases: Error-correcting codes, cryptography

Number System Reference Table

DecimalBinaryHexadecimalOctal
0000000
1000111
2001022
3001133
4010044
5010155
6011066
7011177
81000810
91001911
101010A12
111011B13
121100C14
131101D15
141110E16
151111F17

Bitwise Operations Overview

Bit-Operationen

| Operator | Symbol | Description | Example |
|----------|--------|-------------|----------|
| AND | & | Bitwise AND | 5 & 3 = 1 |
| OR | \| | Bitwise OR | `5 \| 3 = 7` |
| XOR | ^ | Exclusive OR | `5 ^ 3 = 6` |
| NOT | ~ | Bitwise NOT | `~5 = -6` |
| Left Shift | << | Left shift | `5 << 2 = 20` |
| Right Shift | >> | Right shift | `5 >> 1 = 2` |
| Unsigned Right Shift | >>> | Unsigned right shift | `5 >>> 1 = 2` |

Memory Sizes

UnitBytesBitsUnsigned Range
Byte180 - 255
Word2160 - 65,535
DWord4320 - 4,294,967,295
QWord8640 - 18,446,744,073,709,551,615

Two’s Complement Range

BitsMinimumMaximum
8-128127
16-32,76832,767
32-2,147,483,6482,147,483,647
64-9,223,372,036,854,775,8089,223,372,036,854,775,807

Pros and Cons

Advantages of Binary

  • Simple: Only two states (0 and 1)
  • Reliable: Easy to implement without errors
  • Efficient: Optimal for electronic circuits
  • Universal: Foundation of all digital systems

Advantages of Hexadecimal

  • Compact: 4 binary digits = 1 hex digit
  • Readable: Shorter and clearer than binary
  • Standard: Widely used in programming
  • Practical: Ideal for addresses and colors

Disadvantages

  • Abstract: Not intuitive for humans
  • Conversion: Requires mental arithmetic
  • Error-prone: Easy to make mistakes in manual conversion

Common Exam Questions

1. **Convert 175 (decimal) to binary and hexadecimal!**
   175₁₀ = 10101111= AF₁₆

2. **What is the result of 12 & 10 (bitwise AND)?**
   12₁₀ = 1100₂, 10₁₀ = 1010₂ → 1100 & 1010 = 1000= 8₁₀

3. **Explain two's complement!**
   A method for representing negative numbers in binary by inverting all bits and adding 1.

4. **What are hexadecimal numbers used for?**
   Compact representation of binary values, colors, memory addresses, and error codes.

Key References

  1. https://en.wikipedia.org/wiki/Numeral_system
  2. https://en.wikipedia.org/wiki/Two%27s_complement
  3. https://docs.oracle.com/javase/tutorial/java/nutsandbolts/op3.html
Back to Blog
Share:

Related Posts