Bytebook Compiler

Computer Basics

Data Representation

How computers store everything as bits: unsigned and signed integers, two's complement, overflow, floating point, characters with ASCII and Unicode, and images and sound.

5 min read4 runnable examples4-question quiz

Inside a computer, everything — numbers, text, images, music, your code — is a pattern of bits. The meaning depends on how the program interprets those bits.

Unsigned integers

With n bits you can store 2ⁿ patterns: unsigned values 0 to 2ⁿ − 1.

Bits Unsigned range
8 0 to 255
16 0 to 65,535
32 0 to about 4.29 billion
64 0 to about 1.8 × 10¹⁹

Signed integers: two's complement

To store negative numbers, computers use two's complement. The leftmost bit has a negative place value: in 8 bits it is worth −128.

To find the 8-bit pattern for −x: write x in binary, invert all the bits, then add 1.

5 = 0000 0101 → invert → 1111 1010 → add 1 → 1111 1011 = −5

Check: −128 + 64 + 32 + 16 + 8 + 2 + 1 = −5 ✓.

8-bit two's complement ranges from −128 to +127; in general, −2ⁿ⁻¹ to 2ⁿ⁻¹ − 1. Two's complement is used because addition works the same way for positive and negative numbers — the CPU needs only one adder circuit.

C
#include <stdio.h>

void bits8(signed char x) {
    for (int i = 7; i >= 0; i--) putchar((x >> i) & 1 ? '1' : '0');
}

int main(void) {
    signed char values[] = {5, -5, 127, -128, -1};
    for (int i = 0; i < 5; i++) {
        printf("%5d = ", values[i]);
        bits8(values[i]);
        printf("\n");
    }
    return 0;
}
Output
    5 = 00000101
   -5 = 11111011
  127 = 01111111
 -128 = 10000000
   -1 = 11111111

Overflow

When a result does not fit in the available bits, it wraps around:

C
#include <stdio.h>
#include <limits.h>

int main(void) {
    unsigned char u = 255;
    u = u + 1;                                   // 256 does not fit in 8 bits
    printf("255 + 1 in an unsigned char = %d\n", u);
    printf("INT_MAX = %d\n", INT_MAX);
    long long big = (long long)INT_MAX + 1;
    printf("INT_MAX + 1 as a long long = %lld\n", big);
    printf("(int)(INT_MAX + 1LL) = %d\n", (int)(INT_MAX + 1LL));   // wraps to INT_MIN
    return 0;
}
Output
255 + 1 in an unsigned char = 0
INT_MAX = 2147483647
INT_MAX + 1 as a long long = 2147483648
(int)(INT_MAX + 1LL) = -2147483648

The 2038 problem is an overflow waiting to happen: many systems store time as seconds since 1 January 1970 in a signed 32-bit integer, which runs out on 19 January 2038.

Floating point

Real numbers use IEEE 754 floating point — a binary version of scientific notation:

value = (−1)^sign × 1.mantissa × 2^(exponent − bias)

Type Bits Sign Exponent Mantissa Precision
float 32 1 8 23 about 7 decimal digits
double 64 1 11 52 about 15–16 decimal digits

Most decimal fractions cannot be stored exactly, so small errors creep in:

Python
print(0.1 + 0.2)
print(0.1 + 0.2 == 0.3)
print(abs((0.1 + 0.2) - 0.3) < 1e-9)          # compare with a tolerance instead
print(f"{0.1:.20f}")                          # what is really stored
print(1e308 * 10, -1e308 * 10)                 # overflow to infinity
total = 0.0
for _ in range(10):
    total += 0.1                               # tiny errors accumulate
print(total, total == 1.0)
Output
0.30000000000000004
False
True
0.10000000000000000555
inf -inf
0.9999999999999999 False

Characters

Text is stored as numbers too.

  • ASCII (1963) uses 7 bits for 128 characters: 'A' = 65, 'a' = 97, '0' = 48, space = 32, newline = 10.
  • Unicode assigns a code point to every character in every script — over 150,000 of them, including Devanagari, Tamil, emoji and ₹ (U+20B9).
  • UTF-8 encodes Unicode in 1 to 4 bytes, and is identical to ASCII for the first 128 characters. It is the encoding of the web.
Python
for ch in ["A", "a", "0", "₹", "अ", "😀"]:
    data = ch.encode("utf-8")
    print(f"{ch!r}: code point U+{ord(ch):04X} ({ord(ch)}), UTF-8 bytes = {data.hex(' ')} ({len(data)} byte{'s' if len(data) > 1 else ''})")
Output
'A': code point U+0041 (65), UTF-8 bytes = 41 (1 byte)
'a': code point U+0061 (97), UTF-8 bytes = 61 (1 byte)
'0': code point U+0030 (48), UTF-8 bytes = 30 (1 byte)
'₹': code point U+20B9 (8377), UTF-8 bytes = e2 82 b9 (3 bytes)
'अ': code point U+0905 (2309), UTF-8 bytes = e0 a4 85 (3 bytes)
'😀': code point U+1F600 (128512), UTF-8 bytes = f0 9f 98 80 (4 bytes)

Images and sound

  • An image is a grid of pixels; each pixel stores a colour, often as 3 bytes for red, green and blue (24-bit colour). A 1920 × 1080 photo has about 2 million pixels × 3 bytes ≈ 6 MB uncompressed — which is why JPEG and PNG compression matter.
  • Sound is sampled thousands of times per second: CD audio stores 44,100 samples per second, 16 bits each, per channel.

Test yourself

4 questions · pick an answer to check it instantly

  1. 1

    What is the 8-bit two's complement representation of −1?

  2. 2

    What is the range of an 8-bit two's complement integer?

  3. 3

    Why does 0.1 + 0.2 == 0.3 evaluate to false?

  4. 4

    How many bytes does UTF-8 use for an ASCII character like 'A'?