Data representation and character encoding
Priority key · Priorities guide emphasis; they do not remove taught scope.
Exam recall
Binary ↔ hex: group four bits from the right. Preserve required width. A Unicode code point is not its UTF-8 byte sequence.
Bits, bases and ranges priority/medium
The digits are not the value by themselves: their positions and base determine the value. 101 in binary is five; 101 in denary is one hundred and one. Changing representation preserves the quantity, just as writing “five” instead of “5” does.
A bit is 0 or 1; a nibble is 4 bits; a byte is 8 bits. In a positional system, a digit’s contribution is its value multiplied by the base raised to its position, starting at position 0 on the right. Binary uses base 2; denary base 10; hexadecimal base 16 with A–F representing 10–15.
An unsigned n-bit integer has 2ⁿ possible patterns and values 0 to 2ⁿ−1. Four bits represent 0–15, not 1–16. State the unsigned assumption when the question does not specify a signed representation. This pack follows the supplied representation chapter rather than adding unrelated numeric formats.
Conversion procedures priority/high
Binary 1101:
Position 3 2 1 0
Place value 8 4 2 1
Digit 1 1 0 1
Contribution 8 + 4 + 0 + 1 = 13 denaryRepeated division works in the opposite direction: dividing by the base removes the rightmost place and leaves that digit as the remainder. That is why remainders are produced right-to-left. The first remainder is the least significant digit, not the first digit to write.
| Conversion | Reliable procedure |
|---|---|
| Binary → denary | Add the weights of positions containing 1. |
| Denary integer → binary | Repeatedly divide by 2; read remainders from last to first. Handle zero explicitly in an algorithm. |
| Hex → denary | Multiply each digit value by its power of 16 and sum. |
| Binary ↔ hex | Group bits into sets of four from the right; pad the left with zeroes if needed. Convert each nibble separately. |
| Denary integer → hex | Divide repeatedly by 16 and map remainders 10–15 to A–F. |
Hexadecimal is shorter and easier for humans to read/copy than long binary strings, while each hex digit maps exactly to four bits. It does not change the underlying value or mean the computer stores the number as human-readable hex characters.
Where the bases are used priority/medium
| Base | Example | Why it fits |
|---|---|---|
| Decimal | Display an order quantity of 25 | Familiar human-facing notation. |
| Binary | Store the value as a bit pattern | Represents data in digital systems. |
| Hexadecimal | RGB colour #19A0FF or a memory address | Compact notation: one hex digit maps to four bits. |
Hex: 0 A F 0
↓ ↓ ↓ ↓
Binary: 0000 1010 1111 0000
Result: 00001010 11110000Keep every nibble when the required output specifies four bits per input digit.
Characters and encodings priority/high
A character set assigns numeric codes to characters. An encoding specifies how those codes are represented as bytes. ASCII uses 7-bit codes for 128 characters. An ASCII character may be stored in an 8-bit byte with a leading zero. Unicode provides a much larger character repertoire across languages and symbols. Unicode is not universally 16 bits per character: UTF-8, for example, uses variable-length encodings. The first 128 Unicode code points match ASCII, and UTF-8 encodes these using the same single-byte values.
ord("A") returns its code point, 65; chr(65) returns "A". A code point’s hexadecimal label such as U+1F631 identifies a number; its numeric conversion is different from asking for its encoded UTF-8 bytes.
Exam mistakes
Keep leading zeroes when a fixed width is requested. Label the base. Do not confuse the numeric value 65 with the two-character string
"65".
Worked example — adapted from HCI 2024 Q6
Convert hexadecimal DAB to denary and binary.
Denary: 13×16² + 10×16 + 11 = 3499. Binary: D→1101, A→1010, B→1011, so 110110101011₂. Converting through nibble groups preserves every position and avoids repeated division.
Writing the conversion algorithm priority/high
When asked for the algorithm, bin() or hex() may bypass the assessed skill. Repeated division generates the least significant digit first, so prepend it (or reverse the collected digits at the end):
def denary_to_hex(number):
# Contract: number is a nonnegative integer.
digits = "0123456789ABCDEF"
if number == 0: # Without this case, the loop would return empty text.
return "0"
result = ""
while number > 0:
result = digits[number % 16] + result # Prepend the next rightmost digit.
number //= 16 # Remove that base-16 place.
return result
def binary_text(number):
# Recursive version; contract: number is a nonnegative integer.
if number < 2:
return str(number)
return binary_text(number // 2) + str(number % 2) # Higher places return first.For 12, binary_text waits for binary_text(6), then (3), then (1); concatenating returned digits gives "1100". This is text representing twelve in binary, not the denary integer one thousand one hundred.
Practice
Exam focus: HCI 2023 Q4, HCI 2024 Q6 and ASRJC 2025 Q5 use conversions/encoding. In a calculation, show place-value products or nibble groups; in an explanation, distinguish the character repertoire from the byte encoding. The exact originals are in HCI 2024 p.4 and ASRJC 2025 p.4.
Answering approach: identify source base → identify target base/width → choose the shortest justified conversion → pad only if required → label the result. Hex-to-binary does not require a detour through denary.
02A — adapted from HCI 2023 Q4. Convert hexadecimal 1C2 to denary and 12-bit binary. Explain one practical advantage of hexadecimal over binary for humans.
450
0001 0110 0002
Hexadecimal is shorter and easier for human to read and copy
02B — adapted from ASRJC 2025 Q5. The ASCII code for M is 77. Write its 8-bit representation. Convert Unicode code point U+1F631 to denary. Explain why Unicode is useful for messaging beyond ASCII, and why “Unicode always needs two bytes” is inaccurate.
(is 8-bit representation binary and 8 slots)
0100 1101
1F631 base 16 = 128561 base 10
Hex is useful as it is shorter and easier for human reading
Why Unicode always needs two bytes?
For a max unicode, FFFFF, it would be 1048575, which is beyond max 8 bit binary can carry which is 255
Hints
02A: keep all three nibble groups. 02B: use five powers of 16; distinguish a code point from an encoding.
02C — original, conversion algorithm. Write hex_to_binary(text) for a nonempty uppercase hexadecimal string, returning four bits for every digit. Do not use bin() or int(text, 16). Test "0A" and "F0"; explain why the first result starts with zeroes.
HCI Data Representation Practice Question 2
(a) Decimal numbers to binary numbers
Non-Recursive
# Non-Recursive
def dec_to_bin(number):
# Special case
if number == 0:
return "0"
answer = ""
while number > 0:
# Remainder becomes the next binary digit
remainder = str(number % 2)
# Put the remainder at the front of the answer
answer = remainder + answer
# Update number to the quotient so the loop progresses
number = number // 2
return answer
Recursive
# Recursive
def dec_to_bin(number):
# base case
if number < 2:
return str(number)
return dec_to_bin(number // 2) + str(number % 2)(b) Decimal numbers to hexadecimal numbers
Non-Recursive
# Non-Recursive
HEX_DIGITS = "0123456789ABCDEF"
def dec_to_hex(number):
if number == 0:
return "0"
answer = ""
while number > 0:
# Remainder is an integer from 0 to 15
remainder = number % 16
# Convert it to the corresponding hexadecimal character
hex_digit = HEX_DIGITS[remainder]
# Add the digit to the front
answer = hex_digit + answer
# Continue converting the quotient
number = number // 16
return answer
Recursive
# Recursive
HEX_DIGITS = "0123456789ABCDEF"
def dec_to_hex(number):
# base case
if number < 16:
return HEX_DIGITS[number]
# recursive case
return dec_to_hex(number // 16) + HEX_DIGITS[number % 16]
# Example
dec_to_hex(2748)
= dec_to_hex(171) + "C"
= dec_to_hex(10) + "B" + "C"
= "A" + "B" + "C"
= "ABC"(c) Binary numbers to decimal numbers
Non-Recursive
# Non-Recursive
def bin_to_dec(number):
answer = 0
no_of_bin = len(number)
for digit in number:
answer = answer + int(digit) * 2 ** (no_of_bin - 1)
no_of_bin -= 1
return answerChatGPT Ver:
def bin_to_dec(number):
answer = 0
for i in number:
answer = answer * 2 + int(i)
return answerRecursive
# Recursive
def bin_to_dec(number):
# base case
if len(number) == 1:
return int(number)
# recursive case
return bin_to_dec(number[:-1]) * 2 + int(number[-1])Trace "1101"
bin_to_dec("1101")
= bin_to_dec("110") × 2 + 1bin_to_dec("110")
= bin_to_dec("11") × 2 + 0bin_to_dec("11")
= bin_to_dec("1") × 2 + 1到达 base case:
bin_to_dec("1") = 1开始返回:
bin_to_dec("11")
= 1 × 2 + 1
= 3bin_to_dec("110")
= 3 × 2 + 0
= 6bin_to_dec("1101")
= 6 × 2 + 1
= 13(d) Hexadecimal numbers to decimal numbers
Non-Recursive
# Non-Recursive
HEX_DIGITS = "0123456789ABCDEF"
def hex_to_dec(number):
answer = 0
for i in number:
value = HEX_DIGITS.index(i)
answer = answer * 16 + value
return answerRecursive
# Recursive
HEX_DIGITS = "0123456789ABCDEF"
def hex_to_dec(number):
# base case
if len(number) == 1:
return HEX_DIGITS.index(number)
# recursive case
return hex_to_dec(number[:-1]) * 16 + HEX_DIGITS.index(number[-1])(e) Binary numbers to hexadecimal numbers
Use Mapping:
since there are only 16 variations
HEX_DIGITS = "0123456789ABCDEF"
BINARY_NIBBLES = [
"0000", "0001", "0010", "0011",
"0100", "0101", "0110", "0111",
"1000", "1001", "1010", "1011",
"1100", "1101", "1110", "1111"
]
Non-Recursive
# Non-Recursive
# Mapping
HEX_DIGITS = "0123456789ABCDEF"
BINARY_NIBBLES = [
"0000", "0001", "0010", "0011",
"0100", "0101", "0110", "0111",
"1000", "1001", "1010", "1011",
"1100", "1101", "1110", "1111"
]
# Code
def bin_to_hex(number):
# Step 1: add leading zeroes
while len(number) % 4 != 0:
number = "0" + number
answer = ""
# Step 2: process four digits at a time
for i in range(0, len(number), 4):
nibble = number[i:i + 4]
# Step 3: convert the nibble into a value
# (value is a digit 0-15)
value = BINARY_NIBBLES.index(nibble)
# Step 4: convert the value into a hexadecimal digit
hex_digit = HEX_DIGITS[value]
# Step 5: add the digit to the answer
answer = answer + hex_digit
return answer
Trace "101101"
使用 bin_to_hex("101101") 作为 test case。
Step 1 — Add leading zeroes
"101101" 的 length 是 6,不是 4 的倍数,所以 while loop 在左边加入 leading zeroes:
101101 length 6
0101101 length 7
00101101 length 8现在 8 % 4 == 0,所以 while loop 停止,number 是 "00101101"。
Step 2 — Initialise the accumulator
answer = ""answer 是 accumulator,用来逐个储存转换完成的 hexadecimal digits。
Step 3 — Process one nibble per iteration
for i in range(0, len(number), 4):此时相当于 range(0, 8, 4),所以 i 依次是 0 和 4。number[i:i + 4] 从 index i 开始读取四个 digits;ending index 不包括在 slice 内。
| iteration | i | number[i:i + 4] | value | hex_digit | answer |
|---|---|---|---|---|---|
| 1 | 0 | "0010" | 2 | "2" | "2" |
| 2 | 4 | "1101" | 13 | "D" | "2D" |
First iteration:
number = 0 0 1 0 1 1 0 1
index 0 1 2 3 4 5 6 7
└─────┘
"0010"
BINARY_NIBBLES.index("0010") = 2
HEX_DIGITS[2] = "2"
answer = "" + "2" = "2"Second iteration:
BINARY_NIBBLES.index("1101") = 13
HEX_DIGITS[13] = "D"
answer = "2" + "D" = "2D"Final result
101101₂ → 0010 1101₂ → 2D₁₆因此 return answer 返回 "2D"。
Recursive
# Recursive
HEX_DIGITS = "0123456789ABCDEF"
BINARY_NIBBLES = [
"0000", "0001", "0010", "0011",
"0100", "0101", "0110", "0111",
"1000", "1001", "1010", "1011",
"1100", "1101", "1110", "1111"
]
def bin_to_hex_recursive(number):
# base case
if len(number) <= 4:
nibble = number.zfill(4) # zfill(4) add leading 0
value = BINARY_NIBBLES.index(nibble)
return HEX_DIGITS[value]
# recursive case
previous_digits = number[:-4]
last_nibble = number[-4:]
value = BINARY_NIBBLES.index(last_nibble)
hex_digit = HEX_DIGITS[value]
return bin_to_hex_recursive(previous_digits) + hex_digit(f) Hexadecimal numbers to binary numbers
Non-Recursive
# Non-Recursive
# Mapping
HEX_DIGITS = "0123456789ABCDEF"
BINARY_NIBBLES = [
"0000", "0001", "0010", "0011",
"0100", "0101", "0110", "0111",
"1000", "1001", "1010", "1011",
"1100", "1101", "1110", "1111"
]
answer = "" # DONT FORGET THIS
def hex_to_bin(number):
for i in number:
value = HEX_DIGITS.index(i)
answer = answer + BINARY_NIBBLES[value]
return answerRecursive
# Recursive
HEX_DIGITS = "0123456789ABCDEF"
BINARY_NIBBLES = [
"0000", "0001", "0010", "0011",
"0100", "0101", "0110", "0111",
"1000", "1001", "1010", "1011",
"1100", "1101", "1110", "1111"
]
def hex_to_bin(number):
# base case
if len(number) == 1:
value = HEX_DIGITS.index(number)
return BINARY_NIBBLES[value]
# recursive case
previous_digits = number[:-1] # how it reduces to the base case by kicking out the last digit
last_digit = number[-1]
value = HEX_DIGITS.index(last_digit)
return hex_to_bin(previous_digits) + BINARY_NIBBLES[value]
Trace hex_to_bin("2AF")
Call 1
hex_to_bin("2AF")检查 base case:
len("2AF") == 1 # False执行 recursive case:
previous_digits = "2A"
last_digit = "F"
value = 15因此:
hex_to_bin("2AF")
= hex_to_bin("2A") + "1111"但 hex_to_bin("2A") 还没有答案,所以这个 function call 会在 call stack 中等待。
Call 2
hex_to_bin("2A")检查:
len("2A") == 1 # False执行:
previous_digits = "2"
last_digit = "A"
value = 10因此:
hex_to_bin("2A")
= hex_to_bin("2") + "1010"它也要等待 hex_to_bin("2") 的答案。
Call 3:到达 base case
hex_to_bin("2")检查:
len("2") == 1 # True所以:
value = HEX_DIGITS.index("2") # 2
return BINARY_NIBBLES[2] # "0010"现在不再产生新的 recursive call,开始返回答案。
从 call stack 返回
hex_to_bin("2") 返回:
"0010"所以等待中的 hex_to_bin("2A") 可以完成:
hex_to_bin("2A")
= hex_to_bin("2") + "1010"
= "0010" + "1010"
= "00101010"然后最外层也可以完成:
hex_to_bin("2AF")
= hex_to_bin("2A") + "1111"
= "00101010" + "1111"
= "001010101111"最终答案:
hex_to_bin("2AF") # "001010101111"整个过程的简写
hex_to_bin("2AF")
= hex_to_bin("2A") + "1111"
= hex_to_bin("2") + "1010" + "1111"
= "0010" + "1010" + "1111"
= "001010101111"Revision checklist
- 02.1 Explain bit, byte, nibble, base and positional value.
- 02.2 Convert positive integers between denary, binary and hexadecimal in all six directions, showing working.
- 02.3 Group binary digits into nibbles and preserve required leading zeroes.
- 02.4 State suitable computing applications and advantages of hexadecimal.
- 02.5 Write iterative base-conversion code without relying on a conversion shortcut when an algorithm is requested.
- 02.6 Trace or write a recursive conversion and distinguish a number from a string representation.
- 02.7 Explain the need for character encoding and compare standard ASCII with Unicode.
- 02.8 Use ord() and chr() correctly in a supplied character-processing algorithm.
- 02.9 Test conversion code using zero if allowed, powers of a base, single digits and multi-digit values.
Visual revision mindmap

Open this mindmap and its text version · All 21 mindmaps
Your mindmap framework
Centre: Data representation and character encoding. Build the six branches below. For each subbranch, add a short definition, a labelled sample and one exam trap from memory; then check the chapter.
flowchart LR C["02 • Revision map"] C --> B0["Bits and place value"] C --> B1["Conversion routes"] C --> B2["Conversion algorithms"] C --> B3["Computing applications"] C --> B4["Characters and encoding"] C --> B5["Visual checks and mistakes"]
-
Bits and place value
- Bit, nibble, byte; 1 nibble = 4 bits.
- Bases 2, 10 and 16; digits allowed in each.
- Digit contribution = digit × base to position.
- Unsigned n-bit range: 0 through 2ⁿ−1.
-
Conversion routes
- Binary/hex to denary: sum weighted digits.
- Denary to binary/hex: repeated division and reverse remainders.
- Binary ↔ hex: one four-bit group per hex digit.
- Fixed width: preserve leading zeroes and label the base.
-
Conversion algorithms
- Input contract: integer quantity or digit string.
- Iterative state: quotient, remainder, output.
- Recursive state: smaller quotient and returned text.
- Hex-string mapping: digit → nibble → concatenation.
-
Computing applications
- Decimal: human-facing quantities.
- Binary: digital data and instructions.
- Hex: compact addresses and RGB notation.
- Same value, different representation; storage versus display.
-
Characters and encoding
- ASCII: 7-bit codes, 128 characters.
- Unicode: code points across scripts and symbols.
- UTF-8: variable-length byte encoding.
- ord and chr: code point ↔ Python character.
-
Visual checks and mistakes
- Draw place-value columns for one conversion.
- Draw 0A → 0000 1010 to preserve width.
- Test zero, a base power, leading zeroes, several digits.
- Avoid: code point = encoded bytes; Unicode always 16 bits.
Close the notes and test the map: explain one branch aloud, sketch its sample, then answer a linked practice question. Mark any missing link to revisit.
Source trail
9569 §§3.1–3.2; school Data Representation PDF pp.1–6; Python Ch.2 character types.
HCI 2023 Q4; 2024 Q6; 2025 Q2(e)(ii), Q3(b).
Source guide records provenance and original-paper locations.