Skip to main content

Ch 2.3 Radix (Number Bases)

Computers are electronic devices capable of processing only 0s and 1s. However, in daily life we primarily use the decimal (base-10) system. To understand variables more deeply, it is important to know how computers store and read values.

1. Understanding Number Bases

A numeral system (radix) is a way of expressing numbers. The base differs depending on how many distinct digits are used.

BaseDigits UsedApplicationExample (representing 10)
Decimal (base-10)0~9 (10 digits)Everyday life10
Binary (base-2)0, 1 (2 digits)Computer internals1010
Octal (base-8)0~7 (8 digits)File permissions, etc.12
Hexadecimal (base-16)09, AF (16 digits)Colors, memory addressesA
The decimal number 15 in each base:

Decimal: 15
Binary: 1111 (1×8 + 1×4 + 1×2 + 1×1)
Octal: 17 (1×8 + 7×1)
Hexadecimal: F (15×1)

Why Do Computers Use Binary?

The basic element of a computer, the transistor, has only two states: current flowing (1) or not flowing (0). All numbers and characters are expressed by combining these two states.

Current flowing:  ━━━━┐     ┌━━━━┐     ┌━━━━
No current: └─────┘ └─────┘
[0] [1] [0] [1] [0] = 01010 = 10 (ten)

2. Using Different Bases in Java

Java uses special prefixes to distinguish different number bases.

BasePrefixExample
Decimal(none)10
Binary0b or 0B0b1010
Octal0 (the digit zero)012
Hexadecimal0x or 0X0xA
public class RadixLiteral {
public static void main(String[] args) {
int decNum = 10; // Decimal
int binNum = 0b1010; // Binary (0b prefix)
int octNum = 012; // Octal (0 prefix)
int hexNum = 0xA; // Hexadecimal (0x prefix)

// All store the same value (10)
System.out.println("Decimal: " + decNum); // 10
System.out.println("Binary: " + binNum); // 10
System.out.println("Octal: " + octNum); // 10
System.out.println("Hex: " + hexNum); // 10

System.out.println("All equal? " + (decNum == binNum && binNum == octNum && octNum == hexNum));
// true - Java processes all of them as decimal internally
}
}
warning

Octal pitfall: 012 is NOT 12 — it is octal 12, which equals decimal 10! Be careful not to accidentally prepend a zero, as it will be interpreted as octal.

int wrong = 010; // Octal 10 = decimal 8 (!)
int right = 10; // Decimal 10

3. Bits and Bytes

bit: The smallest unit of computer storage. Either 0 or 1.
|
├── 4 bits = 1 nibble
|
└── 8 bits = 1 byte
|
├── 1,024 bytes = 1 KB (kilobyte)
|
├── 1,024 KB = 1 MB (megabyte)
|
├── 1,024 MB = 1 GB (gigabyte)
|
└── 1,024 GB = 1 TB (terabyte)
public class BitByteDemo {
public static void main(String[] args) {
// 1 byte = 8 bits -> -128 ~ 127 or 0 ~ 255
byte oneByte = 127;
System.out.println("1 byte max value: " + oneByte);
System.out.println("Binary representation: " + Integer.toBinaryString(oneByte)); // 1111111

// 2 hex digits = 1 byte
int hex1byte = 0xFF; // 11111111 = 255
System.out.println("0xFF = " + hex1byte); // 255

// File size unit conversion
long fileBytes = 5_368_709_120L; // 5 GB in bytes
long fileMB = fileBytes / (1024 * 1024);
long fileGB = fileBytes / (1024 * 1024 * 1024);
System.out.println("File size: " + fileMB + " MB = " + fileGB + " GB");
}
}

4. Using Radix Conversion Methods

Java's Integer class provides various methods for radix conversion.

public class RadixConversion {
public static void main(String[] args) {
int num = 255;

// Decimal -> other base string
System.out.println("Decimal: " + num);
System.out.println("Binary: " + Integer.toBinaryString(num)); // 11111111
System.out.println("Octal: " + Integer.toOctalString(num)); // 377
System.out.println("Hex: " + Integer.toHexString(num)); // ff
System.out.println("Hex (uppercase): " + Integer.toHexString(num).toUpperCase()); // FF

System.out.println("---");

// Other base string -> decimal
// parseInt(string, radix) format
System.out.println("Binary '11111111' = " + Integer.parseInt("11111111", 2)); // 255
System.out.println("Octal '377' = " + Integer.parseInt("377", 8)); // 255
System.out.println("Hex 'FF' = " + Integer.parseInt("FF", 16)); // 255
System.out.println("Hex 'ff' = " + Integer.parseInt("ff", 16)); // 255 (case-insensitive)

// Output in arbitrary base
System.out.println("255 in base 5: " + Integer.toString(255, 5)); // 2010
System.out.println("255 in base 7: " + Integer.toString(255, 7)); // 513
}
}

5. Two's Complement Representation of Negative Numbers

Computers represent negative numbers using the Two's Complement method.

Binary representation of positive 1 (8 bits):
00000001

How to get -1 (Two's Complement):
Step 1: One's complement (invert each bit) 11111110
Step 2: Add 1 11111111

Therefore -1 = 11111111 (8 bits)

Comparison:
1 = 00000001
-1 = 11111111
2 = 00000010
-2 = 11111110
public class TwosComplement {
public static void main(String[] args) {
// Comparing binary representations of positive and negative numbers
System.out.println("1 = " + Integer.toBinaryString(1));
System.out.println("-1 = " + Integer.toBinaryString(-1)); // 32 ones

System.out.println("127 = " + Integer.toBinaryString(127));
System.out.println("-128 = " + Integer.toBinaryString(-128));

// Sign bit (most significant bit)
// Starts with 0 -> positive, starts with 1 -> negative
int positive = 0b01111111; // 127 (positive, MSB=0)
int negative = 0b10000000; // 128... but -128 in signed byte

byte b1 = (byte) 0b01111111; // 127
byte b2 = (byte) 0b10000000; // -128 (sign bit is 1)

System.out.println("0b01111111 as byte: " + b1); // 127
System.out.println("0b10000000 as byte: " + b2); // -128
}
}

6. Big-Endian vs Little-Endian

When storing multi-byte data in memory, there are rules about the order in which bytes are arranged.

Storing integer 0x12345678 (4 bytes):

Big-Endian (most significant byte first):
Address: 0x100 0x101 0x102 0x103
Value: 0x12 0x34 0x56 0x78

Little-Endian (least significant byte first):
Address: 0x100 0x101 0x102 0x103
Value: 0x78 0x56 0x34 0x12
note

Java uses Big-Endian. Because the JVM always uses big-endian, it behaves the same regardless of which platform it runs on. In contrast, most Intel/AMD x86 CPUs use little-endian.

7. Practical Uses of Hexadecimal

Hexadecimal is a compressed, human-readable form of binary and is frequently used in practice.

Color Codes (HTML/CSS)

public class ColorCode {
public static void main(String[] args) {
// Web color codes use the hexadecimal RRGGBB format
// Example: #FF5733 = R:255, G:87, B:51

int color = 0xFF5733; // Store color as hexadecimal

int red = (color >> 16) & 0xFF; // Upper 8 bits
int green = (color >> 8) & 0xFF; // Middle 8 bits
int blue = color & 0xFF; // Lower 8 bits

System.out.printf("Color code: #%06X%n", color);
System.out.printf("R: %d (%02X)%n", red, red);
System.out.printf("G: %d (%02X)%n", green, green);
System.out.printf("B: %d (%02X)%n", blue, blue);
}
}

Output:

Color code: #FF5733
R: 255 (FF)
G: 87 (57)
B: 51 (33)

Memory Address Representation

public class MemoryAddress {
public static void main(String[] args) {
// Object hash code (similar to memory address)
Object obj = new Object();
int hashCode = System.identityHashCode(obj);

System.out.printf("Hash code (decimal): %d%n", hashCode);
System.out.printf("Hash code (hex): 0x%X%n", hashCode);
// Example: Hash code (decimal): 1829164700
// Hash code (hex): 0x6D06D69C
}
}

8. Practical Example: Converting RGB Colors to Hexadecimal

public class RGBConverter {
// Convert RGB values to hex color code
static String toHexColor(int r, int g, int b) {
// Validate each value is in 0~255 range
if (r < 0 || r > 255 || g < 0 || g > 255 || b < 0 || b > 255) {
throw new IllegalArgumentException("RGB values must be in the range 0~255.");
}
return String.format("#%02X%02X%02X", r, g, b);
}

// Parse hex color code into RGB
static int[] fromHexColor(String hexColor) {
// Remove '#' and parse
String hex = hexColor.startsWith("#") ? hexColor.substring(1) : hexColor;
int r = Integer.parseInt(hex.substring(0, 2), 16);
int g = Integer.parseInt(hex.substring(2, 4), 16);
int b = Integer.parseInt(hex.substring(4, 6), 16);
return new int[]{r, g, b};
}

public static void main(String[] args) {
// RGB -> Hex
System.out.println("White (255,255,255): " + toHexColor(255, 255, 255)); // #FFFFFF
System.out.println("Black (0,0,0): " + toHexColor(0, 0, 0)); // #000000
System.out.println("Red (255,0,0): " + toHexColor(255, 0, 0)); // #FF0000
System.out.println("Blue (0,0,255): " + toHexColor(0, 0, 255)); // #0000FF
System.out.println("Java Orange (237,119,50): " + toHexColor(237, 119, 50)); // #ED7732

// Hex -> RGB
int[] rgb = fromHexColor("#1E90FF"); // Dodger Blue
System.out.printf("Dodger Blue #1E90FF: R=%d, G=%d, B=%d%n", rgb[0], rgb[1], rgb[2]);
// Dodger Blue #1E90FF: R=30, G=144, B=255

// Same value in different bases
System.out.println("\n=== Same Value in Various Bases ===");
int value = 255;
System.out.printf("Decimal: %d%n", value);
System.out.printf("Binary: %s%n", Integer.toBinaryString(value));
System.out.printf("Octal: %s%n", Integer.toOctalString(value));
System.out.printf("Hex: %s%n", Integer.toHexString(value).toUpperCase());
}
}

Output:

White (255,255,255): #FFFFFF
Black (0,0,0): #000000
Red (255,0,0): #FF0000
Blue (0,0,255): #0000FF
Java Orange (237,119,50): #ED7732
Dodger Blue #1E90FF: R=30, G=144, B=255

=== Same Value in Various Bases ===
Decimal: 255
Binary: 11111111
Octal: 377
Hex: FF

9. Bitwise Operator Basics (Advanced)

public class BitwiseBasics {
public static void main(String[] args) {
int a = 0b1010; // Decimal 10
int b = 0b1100; // Decimal 12

System.out.println("a = " + Integer.toBinaryString(a) + " (" + a + ")");
System.out.println("b = " + Integer.toBinaryString(b) + " (" + b + ")");

// AND (&): 1 only when both bits are 1
System.out.println("a & b = " + Integer.toBinaryString(a & b) + " (" + (a & b) + ")"); // 1000 = 8

// OR (|): 1 when either bit is 1
System.out.println("a | b = " + Integer.toBinaryString(a | b) + " (" + (a | b) + ")"); // 1110 = 14

// XOR (^): 1 when bits differ
System.out.println("a ^ b = " + Integer.toBinaryString(a ^ b) + " (" + (a ^ b) + ")"); // 0110 = 6

// NOT (~): invert all bits
System.out.println("~a = " + (~a)); // -11

// Left shift (<<): multiply by 2
System.out.println("a << 1 = " + (a << 1)); // 20 (10 * 2)

// Right shift (>>): divide by 2
System.out.println("a >> 1 = " + (a >> 1)); // 5 (10 / 2)
}
}
tip

Practical uses of bitwise operators:

  • n & 1: Check even/odd (0 = even, 1 = odd)
  • n << 1: Multiply by 2 (faster than multiplication)
  • n >> 1: Divide by 2
  • a ^ b ^ b == a: Swap using XOR property

Summary

  • Binary: computer internal representation (0b prefix)
  • Octal: used for file permissions, etc. (0 prefix — be careful!)
  • Hexadecimal: colors, memory addresses, hash values (0x prefix)
  • Radix conversion: Integer.toBinaryString(), Integer.toHexString(), Integer.parseInt(str, radix)
  • Two's complement: computer's method for representing negative numbers
  • Big-endian: byte storage order used by Java's JVM
  • 1 byte = 8 bits= 2 hexadecimal digits