Binary, Hexadecimal & Number Representation
Boolean Algebra & Digital Logic
Chapter 9 · Binary, Hexadecimal & Number Representation
Every chapter so far has quietly assumed numbers arrive as bits. This chapter asks the question directly — and answers a mystery Chapter 2 left open along the way: why ~True really does equal -2, not by accident, but by design.
Binary and Hexadecimal: The Same Number, Two Notations
Binary is positional notation base 2. Hexadecimal (base 16) exists because it aligns perfectly with binary in a way decimal never can: each hex digit represents exactly 4 bits, with no remainder.
173 in binary: 10101101. Split into 4-bit groups: 1010 and 1101 — decimal 10 and 13, i.e. hex A and D. Result: 0xAD, confirmed to equal 173 exactly.
Two's Complement: How Negative Numbers Actually Work
A naive "sign bit" scheme (flip the top bit to mean negative) has two real problems: it creates two representations of zero (+0 and -0), and ordinary addition breaks unless the hardware special-cases signs. Two's complement avoids both: to negate a number, invert every bit, then add 1.
+3 = 0011. Inverting gives 1100; adding 1 gives 1101 — the encoding of -3. +5 → -5 = 1011. There's exactly one encoding of zero (0000), and the 4-bit range is -8 to 7 — deliberately asymmetric, one more negative value than positive, since 0 itself uses up one of the 16 available patterns on the positive side.
The Real Payoff: Chapter 7's Own Adder Needs No Changes at All
This is the entire reason two's complement is universal: a ripple-carry adder built with zero awareness of signs correctly computes negative results, purely because of how the bit patterns are chosen.
0011 (+3) and 1101 (-3) through the exact same full-adder chain from Chapter 7: result bits 0000, with a discarded final carry-out of 1 — zero, exactly correct. Adding 0101 (+5) and 1011 (-5): same result, 0000. No special subtraction circuit, no sign-checking logic — the identical hardware from Chapter 7 handles both positive and negative numbers correctly, simply because the encoding was chosen to make that true.
Closing the Loop: Why ~True Really Is -2
Chapter 2 flagged ~True == -2 as a real, verified gotcha without explaining why. In two's complement, bitwise complement and negation are related by a clean identity:
~x = -x - 1, for every value checked: ~5=-6 (-5-1=-6), ~10=-11, ~100=-101, all matching exactly. Applied to Chapter 2's own case: True acts as 1, so ~True = -1-1 = -2 — not a quirk of Python's own boolean handling, but two's complement working exactly as designed, on a value that happened to be a boolean.
Arithmetic vs. Logical Right Shift
Right-shifting a negative number needs to decide what to fill the vacated high bits with. Python's >> is an arithmetic shift — it fills with the sign bit, preserving negativity and behaving like floor division by 2.
-8 >> 1 = -4. -7 >> 1 = -4 (floor of -3.5). -1 >> 1 = -1 — stays negative forever under repeated arithmetic shifting, never reaching 0 the way a logical (zero-filling) shift would. Some languages (Java's >>>, for instance) offer a separate logical shift operator specifically because arithmetic and logical shifts genuinely disagree on negative inputs.
Real Relevance
Bitwise operators (&, |, ^, ~, <<, >>) operate directly on these representations — Chapter 2's own flags/bitmasks are binary representation in action, and every value stored anywhere in a running program is, physically, one of the encodings this chapter just formalized.
Number Representation in Code
Hands-On Exercises
Convert 202 to binary, then group it into 4-bit nibbles and convert each nibble to hexadecimal, confirming your hex result equals 202 when checked directly.
Encode +6 and -6 in 4-bit two's complement (showing the invert-then-add-1 process for the negative value), then add the two 4-bit patterns using Chapter 7's own full-adder chain, showing each stage's SUM and COUT, and confirm the result is 0000 with the carry-out discarded.
Using this chapter's own ~x = -x-1 identity, predict the value of ~(-5) without computing it directly first, then verify your prediction. Explain in one sentence why applying ~ twice in a row (~~x) always returns the original value x.
Chapter 9 Quick Reference
- Hex aligns exactly with binary — each hex digit is 4 bits, no remainder
- Two's complement: invert all bits, add 1 — fixes sign-magnitude's double-zero and broken-addition problems
- 4-bit range is
-8to7— deliberately asymmetric, exactly one representation of zero - Verified directly: Chapter 7's own unmodified adder correctly computes
+x + (-x) = 0— no special subtraction circuitry needed - Closed the loop on Chapter 2:
~x = -x-1—~True=-2was two's complement working exactly as designed - Arithmetic right shift sign-extends negative numbers; logical shift zero-fills — genuinely different results, real cross-language relevance
- Next chapter: Capstone — designing a small digital circuit