When I first started digging into cryptography, I realized something quickly — before you can understand ciphers, encryption, or any real crypto concept, you need a solid grip on how computers actually represent characters. Numbers, binary, hex — it all starts there.
So I wrote two small Python programs that build these tables from scratch. Sounds simple, but honestly it clicked a lot of things into place for me. Let me walk you through both.
What We're Building
Program 1 — A table of uppercase letters (A–Z) with their decimal values (0–25), plus an arithmetic operation that adds 3 to each value.
Program 2 — A full ASCII table (characters 0–127) showing each character in Binary, Octal, Decimal, and Hexadecimal.
Program 1: Uppercase Alphabet Table with Arithmetic
The Problem
Map every uppercase letter A–Z to a number (A=0, B=1, ... Z=25), display the original table, then add 3 to every value and display an updated table.
This is actually the foundation of the Caesar cipher — shifting letters by a fixed number. That "add 3" operation? That's exactly what Caesar did.
The Code
print("Original Table:")
print("Letter\tDecimal")
letters = []
values = []
# A-Z Loop
for i in range(26):
letter = chr(65 + i) # ASCII of A = 65
value = i
letters.append(letter)
values.append(value)
print(f"{letter}\t{value}")
print("\nAfter Adding 3:")
print("Letter\tNew Value")
for i in range(26):
new_value = values[i] + 3
print(f"{letters[i]}\t{new_value}")
Step-by-Step Breakdown
1. chr(65 + i) — How we get letters from numbers
In Python, chr() converts an integer to its ASCII character. Since A has ASCII value 65, chr(65) gives 'A', chr(66) gives 'B', and so on up to chr(90) which is 'Z'.
print(chr(65)) # Output: A
print(chr(90)) # Output: Z
2. Storing letters and values in lists
We build two parallel lists — letters and values — so we can loop over them separately for the updated table.
3. Adding 3 to each value
new_value = values[i] + 3
This shifts every letter's number by 3. In cryptography terms, this is a Caesar cipher with shift=3. A (0) becomes 3, B (1) becomes 4, and so on.
4. Tab-separated output with \t
Using \t gives clean columnar output in the terminal without needing any external libraries.
Screenshot
How to Run
python alphabet_table.py
Expected Output (partial)
Original Table:
Letter Decimal
A 0
B 1
C 2
...
Z 25
After Adding 3:
Letter New Value
A 3
B 4
C 5
...
Program 2: Full ASCII Table — Binary, Octal, Decimal, Hex
The Problem
Print all 128 standard ASCII characters with their representations in four number systems: Binary, Octal, Decimal, and Hexadecimal — all in a clean tabular format.
The Code
print("Char\tDecimal\tBinary\t\tOctal\tHex")
for i in range(128): # standard ASCII
char = chr(i)
decimal = ord(char)
binary = bin(i)
octal = oct(i)
hexa = hex(i)
print(f"{char}\t{decimal}\t{binary}\t{octal}\t{hexa}")
Step-by-Step Breakdown
1. range(128) — Standard ASCII range
ASCII defines 128 characters (0–127). The first 32 are control characters (non-printable), the rest are printable symbols, digits, and letters.
2. chr(i) — Integer to character
Converts each number to its corresponding ASCII character.
3. ord(char) — Character back to integer
ord() is the reverse of chr(). It takes a character and returns its ASCII decimal value. Useful to verify the round-trip conversion.
print(ord('A')) # 65
print(chr(65)) # A
4. bin(), oct(), hex() — Python's built-in converters
| Function | What it does | Example output |
|---|---|---|
bin(i) |
Converts to binary string | 0b1000001 |
oct(i) |
Converts to octal string | 0o101 |
hex(i) |
Converts to hexadecimal string | 0x41 |
Python automatically adds prefixes (0b, 0o, 0x) so you always know which base you're looking at.
5. f-string formatting with \t
The \t tabs keep all columns aligned in the terminal without needing format() or any padding library.
Screenshot
How to Run
python ascii_table.py
Expected Output (partial)
Char Decimal Binary Octal Hex
A 65 0b1000001 0o101 0x41
B 66 0b1000010 0o102 0x42
C 67 0b1000011 0o103 0x43
...
a 97 0b1100001 0o141 0x61
b 98 0b1100010 0o142 0x62
How to Verify Your Output
For Program 1:
- Check that
Amaps to0andZmaps to25 - After adding 3:
Ashould show3,Zshould show28 - Total rows: exactly 26 in each table
For Program 2:
-
A→ decimal65, binary0b1000001, octal0o101, hex0x41 -
a→ decimal97(lowercase is always 32 more than uppercase) - Total rows: 128 (0–127)
Quick sanity check in Python:
# Verify a few values manually
print(bin(65)) # 0b1000001
print(oct(65)) # 0o101
print(hex(65)) # 0x41
print(ord('A')) # 65
What I Learned
Going through this exercise, a few things clicked that I hadn't fully internalized before:
Every character is just a number. The letter
Aand the number65are the same thing from the machine's perspective. Encryption at its core is just math on these numbers.The Caesar cipher is literally just addition. Adding 3 to each letter's value and the cipher is done. Subtracting 3 decrypts it. That's it.
Number bases aren't scary. Binary, octal, hex — they're just different ways to write the same value. Python's
bin(),oct(), andhex()make conversion trivial, but understanding why they exist (hardware efficiency, readability) matters more than memorizing conversions.chr()andord()are the gateway to text-based cryptography. Every classical cipher — Caesar, Vigenere, ROT13 — uses this same idea of converting text to numbers, operating on them, and converting back.
Common Mistakes
| Mistake | Why it happens | Fix |
|---|---|---|
chr(i) starting from 0 gives weird symbols |
ASCII 0–31 are control characters | Start from range(32, 128) if you only want printable chars |
Forgetting chr(65 + i) and using chr(i) directly |
Off-by-one thinking | A = 65 in ASCII, not 0 |
| Values after adding 3 going past Z (25→28) | Letters only go 0–25 | Use modulo: (value + 3) % 26 for wrapping |
| Binary output looking messy in columns | Binary strings have variable length | Use format(i, '08b') for fixed 8-bit width |
ord() and chr() confused |
Their names aren't obvious |
ord = ordinal (number), chr = character |
Conclusion
These two programs are small, but they sit right at the foundation of everything in cryptography. Before you can implement any cipher — even the simplest one — you need to understand how characters map to numbers and how those numbers can be represented in different bases.
If you're starting your cryptography journey, I'd recommend running both of these, playing with the shift value in Program 1 (try 13 for ROT13), and spending a few minutes reading the ASCII table output carefully. It makes a lot of later concepts much easier to grasp.


Top comments (0)