Quantum Outpost
foundations beginner · 18 min read ·

What Is a Qubit? From Classical Bits to Quantum States

A ground-up introduction to qubits for developers who already know code. Bloch sphere, Dirac notation, the normalization constraint, and why a qubit is not just a probabilistic bit — with runnable Qiskit code.

Prerequisites: High-school algebra, A little Python

If you’re a developer, you already know what a bit is: a register cell that stores either 0 or 1. A byte is eight of them. An integer is 32 or 64. Every piece of software you have ever written is a choreographed dance over flipping classical bits.

A qubit is what happens when you replace that register cell with a physical system governed by quantum mechanics instead of by classical switches. That one substitution is the entire game — every strange, counterintuitive thing people say about quantum computing (superposition, entanglement, interference, exponential speedups) follows from it.

The catch is that “governed by quantum mechanics” requires some new vocabulary. This tutorial teaches that vocabulary from scratch, assuming you know a little linear algebra and a little Python.

Start with the classical bit

A classical bit has one of two values. We can represent them as 2-dimensional column vectors:

0  =  (10),1  =  (01).|0\rangle \;=\; \begin{pmatrix} 1 \\ 0 \end{pmatrix}, \qquad |1\rangle \;=\; \begin{pmatrix} 0 \\ 1 \end{pmatrix}.

This is slightly weird — why use vectors for a thing that has two values? — but it is going to make the leap to qubits painless. Right now, “the register stores 0” means “the state vector of the register is the first basis vector.” “The register stores 1” means “the state vector is the second basis vector.” Nothing else is allowed.

The angle-bracket notation 0|0\rangle is called Dirac notation (or bra-ket notation, but we only need the “ket” half for now). Read it literally as “the ket zero,” and treat it as a name for a column vector.

Now: a qubit is any unit vector in that 2D space

Here is the whole move. A qubit’s state is a unit-length linear combination of those two basis vectors:

ψ  =  α0  +  β1,where α,βC and α2+β2=1.|\psi\rangle \;=\; \alpha\,|0\rangle \;+\; \beta\,|1\rangle, \qquad \text{where } \alpha, \beta \in \mathbb{C} \text{ and } |\alpha|^2 + |\beta|^2 = 1.

That’s it. α\alpha and β\beta are called amplitudes, and they are complex numbers (not just real). The normalization constraint α2+β2=1|\alpha|^2 + |\beta|^2 = 1 says the state vector has length one.

Four things to notice immediately:

  1. Classical bits are a special case. When α=1,β=0\alpha = 1, \beta = 0 you get 0|0\rangle; when α=0,β=1\alpha = 0, \beta = 1 you get 1|1\rangle. A quantum register is a strict superset of a classical one.
  2. Everything in between is a new, legitimate state. 120+121\frac{1}{\sqrt{2}}|0\rangle + \frac{1}{\sqrt{2}}|1\rangle is a perfectly valid qubit state, distinct from both 0|0\rangle and 1|1\rangle. This is what people mean by “superposition.”
  3. The amplitudes are complex, not real. This matters — it’s what allows interference, which we’ll meet soon.
  4. There are infinitely many qubit states. Unlike a classical bit’s two values, a qubit has a continuous landscape of possible states.

Useful named states

A handful of qubit states come up so often they get their own names. Memorize these:

NameKetColumn formWhat it is
`0⟩`0\|0\rangle(10)\begin{pmatrix}1\\0\end{pmatrix}
`1⟩`1\|1\rangle(01)\begin{pmatrix}0\\1\end{pmatrix}
`+⟩`12(0+1)\frac{1}{\sqrt{2}}(\|0\rangle + \|1\rangle)12(11)\frac{1}{\sqrt{2}}\begin{pmatrix}1\\1\end{pmatrix}
`−⟩`12(01)\frac{1}{\sqrt{2}}(\|0\rangle - \|1\rangle)12(11)\frac{1}{\sqrt{2}}\begin{pmatrix}1\\-1\end{pmatrix}
`i⟩`12(0+i1)\frac{1}{\sqrt{2}}(\|0\rangle + i\|1\rangle)12(1i)\frac{1}{\sqrt{2}}\begin{pmatrix}1\\i\end{pmatrix}
`−i⟩`12(0i1)\frac{1}{\sqrt{2}}(\|0\rangle - i\|1\rangle)12(1i)\frac{1}{\sqrt{2}}\begin{pmatrix}1\\-i\end{pmatrix}

Verify the normalization for +|+\rangle: amplitudes are α=β=12\alpha = \beta = \frac{1}{\sqrt{2}}, so α2+β2=12+12=1|\alpha|^2 + |\beta|^2 = \frac{1}{2} + \frac{1}{2} = 1. ✓

Notice +|+\rangle and |-\rangle have identical magnitudes — a measurement would give 50/50 statistics for both. But they are genuinely different states, because of the relative sign (the “phase”). That hidden phase is where quantum algorithms get their power. Hold onto that thought.

A geometric picture: the Bloch sphere

Having memorized ugly column vectors, let’s get a picture. Every qubit state (up to an irrelevant global phase) can be written as:

ψ  =  cos ⁣θ20  +  eiφsin ⁣θ21,|\psi\rangle \;=\; \cos\!\tfrac{\theta}{2}\,|0\rangle \;+\; e^{i\varphi}\sin\!\tfrac{\theta}{2}\,|1\rangle,

where θ[0,π]\theta \in [0, \pi] and φ[0,2π)\varphi \in [0, 2\pi). Those two angles pick out a single point on the unit sphere in 3-D space. That sphere is the Bloch sphere, and every qubit state corresponds to exactly one point on it.

                +z

                 │  |0⟩

      |−i⟩ ─── ─┼─── ─── |+i⟩    +y


        |−⟩ ─── ─┼─── ─── |+⟩     +x

                 │  |1⟩

                −z

Pin down the axes:

  • 0|0\rangle sits at the north pole, 1|1\rangle at the south.
  • +|+\rangle and |-\rangle are on the equator, on the +x+x and x-x axes.
  • i|i\rangle and i|-i\rangle are on the equator, on the +y+y and y-y axes.
  • Every other qubit state lives somewhere on this sphere.

Put your hands on one: your first qubit in Qiskit

Enough algebra. Let’s make a qubit in code, inspect it, and confirm it behaves the way the math says.

Install Qiskit and the simulator primitives:

pip install "qiskit>=2.0" qiskit-aer

Create a qubit in the state 0|0\rangle and read out its amplitudes:

from qiskit import QuantumCircuit
from qiskit.quantum_info import Statevector

# One qubit, one wire, no gates yet
qc = QuantumCircuit(1)
state = Statevector.from_instruction(qc)

print(state)
# Statevector([1.+0.j, 0.+0.j], dims=(2,))

That output tells you α=1,β=0\alpha = 1, \beta = 0 — a fresh qubit in a Qiskit circuit starts in 0|0\rangle.

Now put it into +|+\rangle. The Hadamard gate (H) does exactly this transition — we’ll derive it properly next track, but it’s the one-line lever that turns 0|0\rangle into equal superposition:

qc = QuantumCircuit(1)
qc.h(0)                                   # apply H to qubit 0
state = Statevector.from_instruction(qc)
print(state)
# Statevector([0.70710678+0.j, 0.70710678+0.j], dims=(2,))

Amplitudes α=β=120.707\alpha = \beta = \frac{1}{\sqrt{2}} \approx 0.707. That’s +|+\rangle.

Verify the normalization constraint explicitly:

import numpy as np
amps = state.data
assert np.isclose(np.sum(np.abs(amps) ** 2), 1.0)

You can also get the Bloch-sphere angles directly:

from qiskit.visualization import plot_bloch_multivector
plot_bloch_multivector(state).savefig("plus.png")
# opens a 3-D Bloch sphere with the arrow pointing along +x

Now try the |−\rangle state. The Z gate flips the sign of 1|1\rangle:

qc = QuantumCircuit(1)
qc.h(0)     # into |+⟩
qc.z(0)     # into |−⟩
state = Statevector.from_instruction(qc)
print(state)
# Statevector([ 0.70710678+0.j, -0.70710678+0.j], dims=(2,))

Amplitudes α=12,β=12\alpha = \frac{1}{\sqrt{2}}, \beta = -\frac{1}{\sqrt{2}}: the negative sign is the “phase” that distinguishes |-\rangle from +|+\rangle.

The single most common misconception

Three sentences to burn in:

A qubit in state 120+121\frac{1}{\sqrt{2}}|0\rangle + \frac{1}{\sqrt{2}}|1\rangle is not a qubit that is secretly either 0 or 1 and which we are merely ignorant about. It is in the state 120+121\frac{1}{\sqrt{2}}|0\rangle + \frac{1}{\sqrt{2}}|1\rangle. That state has genuinely different physics than the coin-flip state, and there is an experiment that can tell the difference.

The experiment is the Mach–Zehnder interferometer, and if you ever have 20 minutes you should read about it. The one-paragraph version: a photon passing through two beam splitters ends up in a completely deterministic output port — but only if you don’t peek in the middle. A coin-flip model predicts 50/50 at the output. Reality matches quantum mechanics, not the coin flip.

Why care as a developer? Because every quantum algorithm’s speedup depends on the fact that amplitudes can interfere constructively and destructively. A probability model has no such thing: probabilities can only add. Amplitudes can cancel.

The shapes of things to come

Here’s the ladder we’ll climb over this track and the next:

  1. This tutorial: a single qubit is a unit vector in a 2-D complex space.
  2. Next tutorial: measurement turns an amplitude α\alpha into an outcome with probability α2|\alpha|^2, and also destroys the superposition. This is the Born rule.
  3. Tutorial 3: combine two qubits with a tensor product; some combinations are “separable” and some are entangled. Entanglement is where classical intuition cracks for good.
  4. Track 2: gates are unitary matrices acting on state vectors. Circuits are products of gates. We’ll build Deutsch-Jozsa, your first quantum algorithm.
  5. Track 3 and beyond: Grover, Shor, VQE, error correction, PQC.

Exercises

1. Which of these are valid qubit states?

For each, check normalization (the sum of squared magnitudes must equal 1):

  • 350+451\frac{3}{5}|0\rangle + \frac{4}{5}|1\rangle
  • 120+121\frac{1}{2}|0\rangle + \frac{1}{2}|1\rangle
  • 120+i21\frac{1}{\sqrt{2}}|0\rangle + \frac{i}{\sqrt{2}}|1\rangle
  • 0+1|0\rangle + |1\rangle
Show answers
  1. ✓ — 9/25+16/25=19/25 + 16/25 = 1.
  2. ✗ — 1/4+1/4=1/211/4 + 1/4 = 1/2 \neq 1. Would need dividing by 2\sqrt{2}.
  3. ✓ — 1/2+1/2=11/2 + 1/2 = 1. This is in fact i|i\rangle.
  4. ✗ — unnormalized. Divide by 2\sqrt{2} to turn it into +|+\rangle.

2. Normalize

Normalize 20+3i12|0\rangle + 3i|1\rangle so it is a valid state.

Show answer

Magnitudes squared: 4+9=134 + 9 = 13. Divide the whole thing by 13\sqrt{13}: 2130+3i131\frac{2}{\sqrt{13}}|0\rangle + \frac{3i}{\sqrt{13}}|1\rangle.

3. Code

Write a Qiskit snippet that produces the state i=12(0i1)|-i\rangle = \frac{1}{\sqrt{2}}(|0\rangle - i|1\rangle). (Hint: start from |0⟩, apply H, then the SDG gate, which applies the phase i-i to 1|1\rangle.) Use Statevector.from_instruction to confirm your amplitudes are (1/2,i/2)(1/\sqrt{2}, -i/\sqrt{2}).

Show answer
from qiskit import QuantumCircuit
from qiskit.quantum_info import Statevector

qc = QuantumCircuit(1)
qc.h(0)
qc.sdg(0)
print(Statevector.from_instruction(qc))
# Statevector([0.70710678+0.j, 0.-0.70710678j], dims=(2,))

4. Think

A qubit is described by 2 complex numbers (4 real numbers) minus a normalization constraint (1 real number) minus an irrelevant global phase (1 real number). How many physical real-number parameters does that leave? Where do they show up on the Bloch sphere?

Show answer

2 real parameters — exactly θ\theta (latitude) and φ\varphi (longitude) on the Bloch sphere. The two angles needed to specify a point on a sphere’s surface.

What you should take away

  • A qubit is a unit vector in 2-D complex space — nothing more, nothing less.
  • Dirac notation ψ=α0+β1|\psi\rangle = \alpha|0\rangle + \beta|1\rangle with α2+β2=1|\alpha|^2 + |\beta|^2 = 1 is the single sentence you should be able to write from memory.
  • The Bloch sphere is a picture of that space. Classical bits are two poles; qubits are the whole surface.
  • Superposition is not ignorance — the relative phase between amplitudes is physically real, and it’s the resource every quantum algorithm consumes.

Next up: what happens when you measure. That’s where probability enters the story — and where the plot thickens considerably.


Weekly dispatch

Quantum, for people who already code.

One serious tutorial per week, plus the industry moves that actually matter. No hype, no hand-waving.

Free. Unsubscribe anytime. We will never sell your email.