2.4 Hexadecimal Number System: Base-16 and 4-Bit Nibble Grouping
Convert between binary and hexadecimal by grouping bits into nibbles of four, and read/write hex values including the letter digits A-F without confusing hex '10' with decimal ten.
Hexadecimal (hex) is base-16, and it is by far the most widely used binary shorthand in modern digital systems — memory addresses, register dumps, color codes, and MAC addresses are almost always written in hex. Because 16 = 2^4, each hex digit maps cleanly onto exactly 4 binary bits (a group called a nibble), and because a byte (8 bits) is exactly two nibbles, hex is a natural, compact way to write byte-oriented data: two hex digits per byte instead of eight binary digits.
Sixteen digits: 0-9 and A-F
Because base-16 needs sixteen distinct single-digit symbols but the ordinary decimal digits only supply ten (0-9), hexadecimal extends the digit set with the letters A through F to represent the values ten through fifteen: A=10, B=11, C=12, D=13, E=14, F=15. A single hex digit therefore ranges from 0 (binary 0000) to F (binary 1111), covering all sixteen possible 4-bit patterns.
This lettered extension is purely notational — A through F are not letters in any linguistic sense here, just extra numeral symbols chosen because the Latin alphabet was a convenient, unambiguous source of new single-character digits.
Grouping binary into nibbles
Exactly like octal's 3-bit grouping, hexadecimal's 4-bit grouping turns binary-to-hex conversion into a mechanical lookup rather than an arithmetic computation: split the binary number into groups of 4 bits starting from the LSB, pad the leftmost group with leading zeros if needed, and translate each nibble independently using the 4-bit-to-hex-digit table.
Because a byte is exactly 8 bits = two nibbles, hexadecimal maps one-to-one onto bytes with no padding ever required for byte-aligned data: every byte is exactly two hex digits, which is precisely why memory dumps and byte values in datasheets are almost universally shown in hex.
Reading large hex numbers correctly
A frequent point of confusion is that hexadecimal '10' does not mean the same thing as decimal ten — hex 10 (written 0x10 or 10_16) equals decimal 16, because it represents one full base-16 place plus zero units, just as decimal '10' represents one full base-10 place. The prefix 0x (or a trailing subscript, _16) is the standard way to mark a numeral as hexadecimal and avoid this ambiguity.
Binary-to-hex nibble grouping
'0x' is the standard prefix for hex literals in most programming and HDL languages (e.g., 0xFA); a trailing subscript 16 is the standard mathematical notation. A single hex digit exactly represents one nibble (4 bits); two hex digits exactly represent one byte (8 bits).
Group binary bits into sets of 4, starting from the LSB (right side);
pad the leftmost group with leading zeros if needed.
Hex digit table (4 bits -> 1 hex digit):
0000=0 0001=1 0010=2 0011=3
0100=4 0101=5 0110=6 0111=7
1000=8 1001=9 1010=A 1011=B
1100=C 1101=D 1110=E 1111=F
Prefix/suffix notation: 0xFF or FF_16Code Examples
The 8-bit binary number 11111010 splits cleanly into two 4-bit nibbles: 1111 and 1010. Looking each up in the 4-bit table gives F (for 1111) and A (for 1010), so the full byte is written FA in hexadecimal — far more compact than writing out all 8 binary digits.
1111 1010_2 = FA_16 0xFF is the largest value representable in two hex digits (all bits of a byte set to 1), equal to decimal 255. Adding 1 more rolls over into a third hex digit, 0x100, which equals decimal 256 — not decimal 100, since '100' in hex means one full 16^2 place, not one full 10^2 place.
0xFF = 255_10, but 0x100 = 256_10, not 100.
1111 1010_2
| |
F A
1111 1010_2 = FA_160xFF = F x 16^1 + F x 16^0 = 240 + 15 = 255_10
0x100 = 1 x 16^2 + 0 x 16^1 + 0 x 16^0 = 256_104-bit nibbles mapping to hex digits
Each group of exactly 4 binary bits (a nibble) maps directly to one hexadecimal digit (0-9, A-F).
Binary: 1111 . 1010
\__/ \__/
F A
Hex: F A -> FA_16Important Rules
Hexadecimal is base-16, using digits 0-9 and letters A-F (A=10 ... F=15) to represent sixteen distinct digit values.
Because 16 = 2^4, one hex digit exactly represents a 4-bit nibble; two hex digits exactly represent one 8-bit byte.
0xFF equals decimal 255 (the maximum value of one byte); 0x100 equals decimal 256, not decimal 100.
To convert binary to hex, group bits into sets of 4 from the LSB, padding the leftmost group with zeros if needed, then translate each nibble.
Where this shows up
Memory addresses, CPU register dumps, MAC addresses, IPv6 addresses, and RGB color codes (#FF5733) are all conventionally written in hexadecimal specifically because of its clean, padding-free correspondence to bytes — a habit every software and hardware engineer relies on daily when reading debugger output or datasheet register maps.
Reading 0x100 as if it were decimal 100, because the digits '1', '0', '0' look identical to the decimal numeral.
Recognize the 0x prefix and compute the value using base-16 place weights: 0x100 = 1x16^2 = 256_10.
0xFF = 255 decimal, but 0x100 = 256, not 100 decimal. The visual similarity between hex and decimal numerals using only the digits 0 and 1 is a common source of this exact mistake — always interpret digits according to the number's declared base.
[tricky] What is the decimal value of 0x100? A. 100 B. 256 C. 16 D. 4096
B. 256 — 0x100 = 1x16^2 + 0x16^1 + 0x16^0 = 256 decimal, not 100. Although 0xFF correctly equals 255 decimal, the next value, 0x100, rolls over into the 16^2 place and equals 256 — the numeral '100' is easy to misread as decimal one hundred, but its base-16 place values give a completely different result.
[multiple-choice] What does the hex digit 'D' represent in decimal? A. 4 B. 12 C. 13 D. 15
C. 13 — Hexadecimal extends the ten decimal digits with letters A through F to represent ten through fifteen: A=10, B=11, C=12, D=13, E=14, F=15. So D corresponds to decimal 13.
Convert the binary byte 10110101_2 to hexadecimal, and separately convert the hex value 0x3D to decimal.
10110101_2 splits into 1011 (B) and 0101 (5), giving 0xB5. For 0x3D: 3x16 + 13x1 = 48 + 13 = 61_10 (recall D = 13).
Split the byte into two nibbles for the first part; for the second, use place weights 16^1 and 16^0.