2IC30 · Topic 02
Number Systems & Arithmetic
How computers represent and compute with numbers — bases, two's-complement, overflow and adders.
Positional number systems & conversion
In base b, a digit's value depends on its position: digit aᵢ contributes aᵢ·bⁱ. Decimal is base 10, binary base 2, octal base 8, hexadecimal base 16 (digits 0–9 then A–F = 10–15).
Value of aₙ₋₁…a₀ in base b = Σ aᵢ·bⁱ. Example ⟨10011010⟩₂ = 128+16+8+2 = 154 = ⟨232⟩₈ = ⟨9A⟩₁₆. Binary ↔ octal/hex : group bits — 3 bits per octal digit, 4 bits per hex digit. 1001 1010 → 9 A. Decimal → base b : repeated division with remainder ; read remainders bottom-to-top. Base b → decimal : expand the powers, or use Horner's rule.
Grouping works because b = 2ᵏ: each base-2ᵏ digit packs exactly k bits. To convert between two non-decimal bases, go via binary (if both are powers of two) or via decimal otherwise. Horner's rule evaluates aₙyⁿ+…+a₀ as (((aₙ)y+aₙ₋₁)y+…)+a₀, needing only n multiplications instead of ½n(n+1).
Hex is everywhere: colours (#FF8800), memory addresses, machine code. Programmers read hex because each digit is a clean nibble (4 bits).
Positional number systems & conversion worked examples
2 questions
Common mistakes
- Reading division remainders top-to-bottom instead of bottom-to-top.
- Grouping bits from the wrong end — group from the least-significant bit.
- Forgetting hex digits A–F represent 10–15.
Exam tips
- Q1 always has 3–4 conversions; the fast route between non-decimal bases is via binary or via decimal.
- Show the division-with-remainder ladder for partial credit even if the final digit is wrong.
Memory aids
- Div-remainder result is read B ottom-up (B for 'Backwards').
- 4 bits = 1 hex digit, 3 bits = 1 octal digit.
Positional number systems & conversion practice
2 questions
Representing negative numbers
With n bits you have 2ⁿ patterns. Three schemes split them into positive and negative: Sign-and-magnitude : top bit = sign, rest = magnitude. 1's-complement : negate by flipping all bits. 2's-complement : negate by flipping all bits then adding 1.
For n+1 bits: Scheme Range Zeros Arithmetic Sign-magnitude −(2ⁿ−1)…2ⁿ−1 +0 and −0 needs compare+subtract 1's-complement −(2ⁿ−1)…2ⁿ−1 +0 and −0 end-around carry 2's-complement −2ⁿ…2ⁿ−1 single 0 plain addition ✔ 2's-complement value of aₙ₋₁…a₀ = −aₙ₋₁·2ⁿ⁻¹ + Σ(i negative weight.
The negate trick (invert + 1) works because 2ⁿ − m = (2ⁿ − 1 − m) + 1 = invert(m) + 1. It also un-negates. The one exception: the most-negative number (e.g. 1000 = −8 in 4 bits) has no positive counterpart, so negating it overflows. Sign extension : to widen, replicate the sign bit (−4 = 1100 → 1111 1100). Truncation is safe only if the discarded bits equal the new sign bit. Sign-magnitude is used for floating-point; 2's-complement dominates integer hardware because one adder handles add and subtract.
Every CPU integer unit uses 2's-complement. The asymmetry (one extra negative) is why abs(INT_MIN) overflows in C/Java.
Representing negative numbers worked examples
2 questions
Common mistakes
- Forgetting the +1 step (that gives 1's-complement, not 2's).
- Treating the top 2's-complement bit as +2ⁿ⁻¹ instead of −2ⁿ⁻¹.
- Sign-extending with 0s for a negative number.
Exam tips
- Q1 almost always asks for the 2's-complement representation and sometimes sign-magnitude too — give both if asked.
- State the minimal bit-width carefully: include the sign bit.
Memory aids
- 2's-complement negate: 'flip and add one'.
- Top bit's weight is NEGATIVE in 2's-complement.
Recall the memory aids
0/2 answered
To negate a number in two's complement, every bit and add one.
In two's complement, the top bit's weight is .
Representing negative numbers practice
2 questions
Addition, subtraction, overflow & condition codes
Binary addition works column by column with carries, just like decimal. Subtraction a−b is done as a + (−b) using 2's-complement, so one adder does both.
Overflow = the true result doesn't fit in the available bits. With 2's-complement addition it can only happen when the two operands have the same sign and the result's sign differs. Detection rules (any one): By hand: sign-extend both by one bit, add; overflow if the two left-most result bits differ. Hardware: overflow = carry-into-MSB XOR carry-out-of-MSB (the two most-significant carries differ). The four condition-code flags set after an operation: C Carry — carry-out of the most significant bit. Z Zero — result is all zeros. N Negative — result's MSB is 1. V Overflow — signed overflow (carryₙ ≠ carryₙ₋₁).
The same bit pattern means different things unsigned vs signed, so comparisons depend on interpretation. After computing α−β: relation unsigned signed (2's-comp) α<β C=1 N≠V α=β Z=1 Z=1 α>β C=0 ∧ Z=0 N=V ∧ Z=0 For subtraction, the adder inverts b and forces carry-in=1. The carry flag's meaning for subtraction can differ between processors (borrow vs not-borrow) — state your convention.
Branch instructions (BEQ, BCS, BMI, BVS…) test exactly these flags; signed vs unsigned comparison bugs are a classic source of security vulnerabilities.
Addition, subtraction, overflow & condition codes worked examples
2 questions
Common mistakes
- Checking overflow on unsigned numbers using the signed rule (use the carry for unsigned).
- Forgetting to sign-extend before the by-hand overflow check.
- Reporting overflow when operands had opposite signs (impossible for add).
- Confusing carry (unsigned overflow indicator) with V (signed overflow).
Exam tips
- Q1c almost always says 'explain explicitly how you computed the carry' — show the carry chain.
- Give ALL four flags; each is worth marks.
- Overflow only when signs of operands agree and the result's sign flips.
Memory aids
- Overflow add: 'same signs in, different sign out'.
- V = carry-in-to-MSB XOR carry-out-of-MSB.
Addition, subtraction, overflow & condition codes practice
2 questions
Adders: half, full, ripple & look-ahead
A half adder adds two bits a,b giving sum s and carry c. A full adder adds three bits a,b,cᵢₙ giving s and cₒᵤₜ, so adders can be chained.
Half adder: s = a⊕b, c = a∧b. Full adder: s = a⊕b⊕cᵢₙ, cₒᵤₜ = (a∧b) ∨ (cᵢₙ∧(a⊕b)). A full adder is two half adders plus an OR. Ripple-carry adder : n full adders chained, carry flows along. Simple but the carry must propagate through all n stages — about 2n gate delays (128+ for 64-bit).
The ripple delay is the bottleneck. A carry-look-ahead adder computes carries in parallel from generate gᵢ=aᵢ∧bᵢ and propagate pᵢ=aᵢ⊕bᵢ signals (cᵢ₊₁ = gᵢ ∨ pᵢ∧cᵢ), cutting delay to roughly logarithmic at the cost of more gates. A single add/subtract circuit uses XOR gates (or multiplexers) on the b inputs plus a control line that both inverts b and sets carry-in=1 for subtraction; the top carries also feed the overflow logic.
Real ALUs use look-ahead, carry-select or prefix adders (Kogge-Stone) to hit GHz clocks; the ripple adder is the teaching baseline.
Adders: half, full, ripple & look-ahead worked examples
1 questions
Common mistakes
- Writing full-adder carry without the cᵢₙ term.
- Thinking a half adder can be chained (it has no carry-in).
- Assuming look-ahead has no extra hardware cost.
Exam tips
- 'Draw a full adder using only basic gates' is a recurring Q2 part (e.g. 2022 2d).
- Know why ripple is slow (2n delays) and that look-ahead fixes it.
Memory aids
- Half adder = ⊕ and ∧. Full adder = half + half + OR.
- Ripple = slow chain; look-ahead = parallel carries.
Adders: half, full, ripple & look-ahead practice
2 questions
Codes: Gray, parity, Hamming, ASCII, Huffman
Beyond plain binary, special codes serve goals like error detection, smooth counting, or compression.
Gray code : consecutive values differ in exactly one bit — avoids glitches when several bits would otherwise change at once. Parity bit : one extra bit makes the total number of 1s even (or odd); detects any single-bit error. Hamming code : several check bits let you correct a single-bit error, not just detect it. ASCII : 7/8-bit character code; Unicode : up to 32-bit characters. Huffman code : variable-length — shorter codes for frequent symbols → compression. Self-delimiting codes encode their own length first.
Gray code matters in FSM state assignment and physical encoders: if two state bits changed simultaneously, transient glitches could be sampled. Parity is the cheapest error detection (used in 'parity RAM' and safety-critical CPUs); Hamming distance d lets you detect d−1 and correct ⌊(d−1)/2⌋ errors. Huffman gives the optimal prefix-free code and is also used to choose optimal opcode lengths (expanding opcodes).
QR codes and ECC RAM use Hamming-style correction; ZIP/JPEG use Huffman; rotary encoders use Gray code.
Codes: Gray, parity, Hamming, ASCII, Huffman worked examples
1 questions
Common mistakes
- Thinking parity can correct errors (it only detects single-bit errors).
- Confusing Gray code with binary counting order.
- Forgetting Huffman codes must be prefix-free.
Exam tips
- Codes appear mostly as short Q6 recall — know one sentence on each.
- Link Gray code to FSM state assignment (it reduces glitches).
Memory aids
- Gray = 'one bit at a time'. Parity = detect. Hamming = correct. Huffman = compress.
Codes: Gray, parity, Hamming, ASCII, Huffman practice
2 questions