
From Bit to Qubit: The Shift in Mental Models Software Engineers Need
I can say that I first became interested in quantum computing when I read about the concept of a qubit, as opposed to the familiar bit, in a book by Michio Kaku…
Perhaps it was because, as a software engineer, I was so used to thinking in terms of bits, variables, states, and precisely defined values. As we know, a bit is either 0 or 1. We can store it, read it, copy it, change it, and check it again as many times as we like. Much of our intuition as programmers is built on ideas as simple as these.
Then a new concept appears: the qubit, which, as we will see, has very different properties from the classical bit, for want of a better term.
And I’m afraid this is where the misunderstandings begin, because the first thing we usually hear is that a qubit can be 0 and 1 “at the same time.”
That explanation can be useful for sparking our curiosity, but I think it is insufficient for understanding what it really means to program a quantum computer. It can even lead us to build the wrong mental model.
A qubit is not simply a bit that has learned a new trick. It is a different way to represent and manipulate information, with properties from quantum mechanics that allow us to perform operations in a fundamentally different way.
In this article, I’ll give a brief introduction to the qubit.
From value to state
Let’s start with what we know well. The state of a classical bit belongs to the set:
That’s it.
We can have millions of bits and build extraordinarily complex structures with them, but at any given moment, each individual bit has one of those two values. This may seem obvious, at least to those of us who have been programming since we were young, though perhaps even this once seemed strange or exotic to us.
A qubit is described differently. Its pure state can be written in Dirac notation as:
where and are complex numbers called amplitudes, and they must satisfy:
(To keep things simple, let’s say that Dirac notation is the mathematical language used in quantum mechanics to represent quantum states and operations more compactly.)
Here we find one of the first major shifts in perspective for a programmer: 0 and 1 are no longer the only possible states, but rather the vectors of a basis, usually called the computational basis. The qubit’s state is a normalized vector in a two-dimensional complex vector space.
This means there are infinitely many possible states between and , even though a measurement in the computational basis can only give us one of those two outcomes. At this point, we also realize that quantum computing uses linear algebra to represent the states of quantum algorithms.
We should not think, therefore, that and store two classical values simultaneously. They are amplitudes that form part of the mathematical description of the state.
Amplitudes are not probabilities
Understanding this point is especially important.
Suppose we have:
and perform a measurement in the computational basis. We get:
You might then think that a qubit is nothing more than a kind of probabilistic bit. But it isn’t that either. Can you see how different all of this is from a classical bit?
The amplitudes and are complex numbers, and they preserve information that probability alone cannot represent: phase—yes, those same complex numbers you probably studied in your first year at university.
Imagine two states:
and
If we measure either of them directly in the computational basis, we get 0 or 1 with a 50% probability.
From the perspective of those probabilities, they seem identical, and yet the states are not the same.
The sign introduces a relative phase difference, and that matters because amplitudes can interfere. Later quantum operations can turn that seemingly invisible difference into completely different measurement outcomes. In fact, manipulating phase is key to most quantum computing algorithms.
In my opinion, this is one of the points where programmers have to leave classical intuition behind for good: knowing only the output probabilities does not mean knowing the quantum state.
Another difference: measurement is not the same as reading a variable
There is another deeply ingrained habit among those of us who program: observing the state of our program.
We can pause an application at a breakpoint and calmly check:
counter = 7
enabled = true
status = READY
or something like that. We can even inspect a variable several times without changing its value just by reading it.
With a qubit, things are substantially—and radically—different.
If we prepare:
and measure it in the computational basis, we get 0 or 1, each with probability . After an ideal projective measurement, the state is associated with the outcome we obtained.
That is why measuring a qubit is not the same as querying a variable.
This difference has immediate consequences for how we design and debug quantum algorithm programs. We cannot arbitrarily inspect an unknown state during execution, read its amplitudes, and carry on as if nothing happened. In fact, languages designed specifically for quantum programming reflect this limitation: Q#, for example, does not allow direct access to a qubit’s internal state.
From a developer’s point of view, this can be quite disconcerting at first.
I suspect many developers who become interested in quantum computing reach this point, encounter a tangle of concepts rooted in quantum mechanics, throw in the towel, and give up on it.
We are used to observing a program’s state as a natural part of debugging. In quantum computing, we have to reason more about transformations, probabilities, invariants, and statistical results gathered over multiple runs.
Why? Because nature is fundamentally probabilistic at the quantum level.
The Bloch sphere
Fortunately, we have an exceptionally useful representation for building intuition: the Bloch sphere. Ignoring a physically irrelevant global phase, the pure state of a single qubit can be written as:
The parameters and let us represent the state as a point on the surface of a sphere.
At one pole we have , and at the opposite pole, . The other points represent the different possible superpositions.
I find this representation especially interesting for someone coming from software development, because it helps us stop imagining a qubit as a strange switch that is “on and off at the same time.”

It is more useful to visualize it as a state we can transform through operations.
Single-qubit gates can be interpreted as rotations of this state, up to a global phase. Applying a gate changes its position on the sphere and, with it, the amplitudes and phases that determine how it behaves in subsequent operations and what we can obtain when we measure it.
But we should introduce an important caveat here: the Bloch sphere is an extraordinary representation for a single qubit. We should not naively extrapolate it to an arbitrary system of many qubits, whose state space grows exponentially (another difficult concept to digest).
In quantum computing, we program transformations, not values
Here we find what may be the conceptual shift that matters most to us as software engineers. In classical programming, we constantly write instructions like:
x = 0
x = 1
if x == 1:
...
We think in terms of variables that contain values.
In quantum programming, it is more appropriate to think in terms of preparing a state, transforming it, and finally measuring it.
For example, applying a Hadamard gate to transforms the qubit’s state and produces:
If we immediately measure this state many times in the computational basis, we will observe approximately half 0 outcomes and half 1 outcomes.
But the truly interesting part is not getting an extraordinarily sophisticated random bit generator. It begins when we keep operating on the amplitudes before measuring.
When implementing a quantum algorithm, the task is therefore to modify the phases of its qubits and make different computational paths interfere constructively or destructively. A quantum algorithm is precisely about controlling these transformations so that, at the end of the computation, the resulting distribution of outcomes contains useful information about the problem we are trying to solve.
The famous claim that a quantum computer “tries all the solutions at once” should therefore be treated with great care. A purely quantum phenomenon is difficult to translate into human language (which, after all, is shaped by the material world—or, let’s say, a Newtonian one, with all due caveats and apologies for such a crude comparison). A superposition does not let us read all its components simultaneously.
When quantum algorithms do offer a provable advantage, their power comes from something much subtler than supposed free parallelism.
Our approach to debugging changes too
All of this forces us to reconsider another one of our habits as programmers: debugging.
In a simulator, we can inspect a state vector because it is represented using classical memory. Tools such as the Qiskit library let us visualize statevectors, density matrices, and Bloch spheres for analysis and learning.
However, we must not confuse this convenience of simulation with the behavior of real quantum hardware.
A classical program can be debugged by directly observing much of its internal state. A quantum program has to be analyzed in terms of state preparation, gates, measurement bases, and statistical distributions. Real systems also introduce noise, decoherence, and operational and measurement errors, making this task even more complicated.
It is another craft we will have to learn, and it radically changes how we have programmed on classical computers.
A qubit is not a better bit
If I had to take away just one idea, it would be this: a qubit is not a more powerful version of a bit, as I have read in some places, nor does it simply store more classical information.
It is the basic unit of information in a different computational model. Its state is represented by complex amplitudes, and its evolution harnesses properties such as superposition, phase, and interference—and, when we work with multiple qubits, entanglement. These are purely quantum phenomena.
For those of us who have spent many years developing software, the main difficulty in getting started with quantum computing may not be learning new gates, memorizing circuits, or using a different SDK. All of that can be learned.
The hard part is leaving behind certain intuitions and habits in how we solve problems. That is why I say this is a new computing paradigm.
We have to accept that observing can change what we are observing; that a phase that does not appear directly in a measurement can be decisive a few operations later; that we cannot casually copy an unknown quantum state; and that our program is no longer simply about moving known values between memory locations.
We have to learn to think in terms of states, transformations, amplitudes, and interference, along with all the mathematical foundations they require.
The qubit was one of the concepts that sparked my interest in quantum computing for precisely this reason. After many years of thinking in terms of classical software, discovering that the most basic unit of information itself forced me to reconsider ideas that had seemed obvious was especially intriguing—and quite a shock at first.
And I think that is a good starting point for any developer who wants to get into this field.
Before trying to understand algorithms such as Grover’s, Shor’s, or QAOA, it is worth taking enough time to pause here, because this is the foundation for everything that follows.
First, we need to learn what a qubit really means.
And, above all, stop thinking of it as a strange bit.