Java Number Systems: Binary, Octal and Hex
Java Number Systems
Every number in a Java program is stored as binary — ones and zeros — but you can write and display it in four different bases: decimal (base 10), binary (base 2), octal (base 8) and hexadecimal (base 16). Knowing how these bases relate explains bitwise operators, colour codes, file permissions, memory addresses, and why int x = 010; is not ten.
What Is a Number System?
A number system (or base) decides how many different digits are available and what each position is worth. In base 10 there are ten digits, 0 to 9, and each position is worth ten times the one to its right: 345 means 3 × 100 + 4 × 10 + 5 × 1.
The same idea works for any base. Only the number of digits and the value of each position change.
| System | Base | Digits | Position values (right to left) | Java literal prefix |
|---|---|---|---|---|
| Binary | 2 | 0–1 | 1, 2, 4, 8, 16, … | 0b or 0B |
| Octal | 8 | 0–7 | 1, 8, 64, 512, … | 0 (a leading zero) |
| Decimal | 10 | 0–9 | 1, 10, 100, 1000, … | none |
| Hexadecimal | 16 | 0–9, A–F | 1, 16, 256, 4096, … | 0x or 0X |
In hexadecimal, the letters A to F stand for the values 10 to 15, because base 16 needs sixteen single-character digits.
Writing Numbers in Different Bases in Java
Java lets you write an integer literal in any of the four bases. All of them produce exactly the same int value in memory — the base only affects how you type it.
1public class NumberLiterals {
2 public static void main(String[] args) {
3 int decimal = 42;
4 int binary = 0b101010; // 32 + 8 + 2
5 int octal = 052; // 5 × 8 + 2
6 int hex = 0x2A; // 2 × 16 + 10
7
8 System.out.println(decimal + " " + binary + " " + octal + " " + hex);
9
10 int mask = 0b1111_0000; // underscores group digits for readability
11 long card = 1234_5678_9012_3456L;
12 System.out.println(mask + " " + card);
13 }
14}Output:
42 42 42 42
240 1234567890123456
Underscores between digits (Java 7 and later) are ignored by the compiler. They're especially useful in binary literals, where long runs of ones and zeros are hard to read.
Converting Between Bases by Hand
Decimal to Another Base: Divide and Collect Remainders
Divide the number by the target base, write down the remainder, and repeat with the quotient until it reaches 0. Reading the remainders from last to first gives the digits.
Converting 45 to binary:
| Step | Division | Quotient | Remainder |
|---|---|---|---|
| 1 | 45 ÷ 2 | 22 | 1 |
| 2 | 22 ÷ 2 | 11 | 0 |
| 3 | 11 ÷ 2 | 5 | 1 |
| 4 | 5 ÷ 2 | 2 | 1 |
| 5 | 2 ÷ 2 | 1 | 0 |
| 6 | 1 ÷ 2 | 0 | 1 |
Reading the remainders bottom-up gives 101101.
Another Base to Decimal: Multiply by Position Values
Multiply each digit by its position value and add the results. For binary 101101:
1 × 32 + 0 × 16 + 1 × 8 + 1 × 4 + 0 × 2 + 1 × 1 = 45
A faster way to do the same thing in code is to read the digits from left to right and keep a running total: multiply the total by the base, then add the next digit. For 101101 the total goes 1, 2, 5, 11, 22, 45.
Binary to Octal and Hex: Group the Bits
Because 8 = 2³ and 16 = 2⁴, each octal digit is exactly 3 bits and each hex digit is exactly 4 bits. Group the binary digits from the right:
- ›Octal:
101 101→ 5 5 → 55 - ›Hex:
0010 1101→ 2 D → 2D
That direct mapping is why programmers use hex as a compact way to read binary data.
Converting Between Bases with Java Methods
The Integer class (and Long, for 64-bit values) has methods for every common conversion.
1public class BaseConversions {
2 public static void main(String[] args) {
3 int n = 45;
4
5 // decimal -> other bases (returns a String)
6 System.out.println(Integer.toBinaryString(n)); // 101101
7 System.out.println(Integer.toOctalString(n)); // 55
8 System.out.println(Integer.toHexString(n)); // 2d
9 System.out.println(Integer.toString(n, 3)); // any radix from 2 to 36
10
11 // other bases -> decimal (returns an int)
12 System.out.println(Integer.parseInt("101101", 2));
13 System.out.println(Integer.parseInt("55", 8));
14 System.out.println(Integer.parseInt("2D", 16));
15 System.out.println(Integer.decode("0x2D")); // understands 0x, # and 0 prefixes
16 }
17}Output:
101101
55
2d
1200
45
45
45
45
Integer.toHexString prints lowercase letters. Use .toUpperCase() or String.format("%X", n) when you need uppercase, and String.format("%08X", n) to pad with zeros to a fixed width.
How Negative Numbers Are Stored: Two's Complement
Java's int is a 32-bit signed number stored in two's complement. To get the bit pattern of a negative number, take the positive value's bits, flip every bit, and add 1. The leftmost bit then acts as the sign: 0 for positive, 1 for negative.
1public class TwosComplement {
2 public static void main(String[] args) {
3 System.out.println(Integer.toBinaryString(5));
4 System.out.println(Integer.toBinaryString(-5));
5 System.out.println(Integer.toString(-5, 2)); // keeps the minus sign instead
6 System.out.println(Integer.MAX_VALUE + 1); // wraps around to the minimum
7 }
8}Output:
101
11111111111111111111111111111011
-101
-2147483648
Two's complement is why Integer.MAX_VALUE + 1 silently becomes Integer.MIN_VALUE — adding 1 to 0111…1 produces 1000…0, which is the most negative 32-bit value.
Where You'll Meet Other Bases in Real Code
- ›Hexadecimal — colour codes (
#FF8800), byte dumps, hash values, memory addresses and Unicode escapes such as'é'. - ›Binary — bit flags and masks, used with the bitwise operators
&,|,^and<<. - ›Octal — Unix file permissions such as
chmod 755, where each digit packs read, write and execute bits.
Common Mistakes
Mistake 1 — A Leading Zero Makes a Literal Octal
1int day = 09; // does not compile: 9 is not an octal digit
2int code = 010; // compiles, but the value is 8, not 10Never pad integer literals with zeros for alignment. If you need a fixed-width display, format the output instead: String.format("%02d", day).
Mistake 2 — Parsing a Value Too Large for int
Integer.parseInt("11111111111111111111111111111111", 2) throws NumberFormatException, because that bit pattern is larger than Integer.MAX_VALUE as an unsigned number. Use Integer.parseUnsignedInt(text, 2) or Long.parseLong(text, 2) for full 32-bit patterns.
Mistake 3 — Expecting toBinaryString to Show a Minus Sign
toBinaryString, toOctalString and toHexString treat the value as unsigned and show the raw two's complement bits. Use Integer.toString(value, radix) when you want a human-readable result with a minus sign.
Interview Questions
How do you convert a decimal number to binary without built-in methods?
Repeatedly divide by 2, collect each remainder, and reverse the collected digits at the end. The full program, along with octal and hexadecimal versions, is in the practice programs below.
Why is hexadecimal so common in programming?
Each hex digit represents exactly four bits, so a byte is always two hex digits. That makes long binary values short and readable while still mapping directly to the underlying bits.
What is the output of System.out.println(010 + 0x10)?
- ›
010is octal 8 and0x10is hexadecimal 16.
What range of values can a Java int hold?
From −2,147,483,648 to 2,147,483,647, that is −2³¹ to 2³¹ − 1. The range is asymmetric because zero takes one of the non-negative bit patterns.
FAQs
Does Java have a binary data type?
No. Every integer type (byte, short, int, long) is already stored in binary. Binary, octal and hex are only different ways of writing or displaying the same value.
Can floating-point numbers be written in hexadecimal?
Yes, Java supports hexadecimal floating-point literals such as 0x1.8p1 (which is 3.0), but they're rare outside low-level numeric code.
What does the radix parameter mean?
Radix is another word for base. Integer.parseInt("ff", 16) reads the text as base 16, and Integer.toString(255, 2) writes the value in base 2. Java accepts any radix from 2 to 36.
Summary
A number system defines the digits available and the value of each position; decimal, binary, octal and hexadecimal are just different ways of writing the same stored value. Java lets you write literals in each base with no prefix, 0b, a leading 0, or 0x, and the Integer and Long classes convert between bases in both directions. Negative integers are stored in two's complement, which explains the long bit strings from toBinaryString and the wrap-around at Integer.MAX_VALUE.
What to Read Next
Practice Programs
Put this topic into practice — each program has full code, output and a step-by-step explanation you can run online.
Turns a base-10 integer into its base-2 form by collecting remainders of repeated division by 2.
Reads a string of bits and works out the base-10 value it represents.
Rewrites a base-10 integer in base 8 using the remainders left by repeated division by 8.
Validates an octal string and computes its value in base 10.
Converts a base-10 integer to base 16, mapping remainders 10 to 15 onto the letters A to F.
Parses a hex string, letters in either case, into its base-10 value.