How does binary store 3.14? Floating point, BCD and character codes
Two's complement only handles whole numbers. Here's how computers represent fractions using scientific notation in binary, plus the smaller codes worth knowing - BCD, ASCII and parity bits.
Whole numbers aren't enough
Two's complement (previous lesson) represents integers beautifully, but it has no way to represent or — there's no decimal point anywhere in the scheme. Computers need fractional numbers constantly (physics simulations, graphics, machine learning, your bank balance), so a completely different representation is needed: floating point.
The idea: binary scientific notation
You already know scientific notation: . Floating point does the exact same thing, but in binary, storing three separate pieces instead of one long string of digits:
- Sign — 1 bit: 0 for positive, 1 for negative (much simpler than two's complement here, since floating point doesn't need addition-hardware reuse the same way).
- Exponent — how many places to shift the binary point, similar to the "" part above.
- Mantissa (also called the significand) — the actual digits of precision, similar to the "3.125" part above.
The IEEE 754 standard: 32-bit single precision
Virtually every computer on Earth uses the IEEE 754 standard for floating point. A 32-bit ("single precision") float splits its 32 bits as:
+------+------------------+------------------------------------+
| Sign | Exponent | Mantissa |
| 1 bit| 8 bits | 23 bits |
+------+------------------+------------------------------------+
10000001 = 129 actually means a real exponent of ), specifically so exponents can represent both very large and very small numbers using only unsigned bit patterns, without needing a separate sign bit just for the exponent.
There's also a clever trick called the implicit leading 1: since the mantissa is always normalized to look like (exactly one nonzero digit before the point, just like scientific notation always writing , not or ), that leading 1 never needs to actually be stored — it's assumed for free, effectively giving 23 stored mantissa bits the precision of 24.
Worked example: encoding 5.75
Let's encode into IEEE 754 single precision, step by step.
Step 1 — convert to binary. , and (since ). So .
Step 2 — normalize. Shift the binary point so exactly one digit sits before it: . The exponent is .
Step 3 — bias the exponent. Stored exponent .
Step 4 — drop the implicit leading 1, keep the rest as the mantissa, padded to 23 bits: mantissa bits are0111 followed by zeros: 01110000000000000000000.
Step 5 — assemble: sign (0, positive) + exponent (10000001) + mantissa (01110000000000000000000):
Why floating point loses precision (and why exactly)
With only 23 stored mantissa bits, floating point can only represent finitely many distinct values — it cannot represent every real number exactly, only a fixed set of "grid points" spaced increasingly far apart as numbers get larger. Some simple decimal fractions, like , don't have an exact finite binary representation at all (much like has no exact finite decimal representation — it's forever). This is precisely why a calculator or programming language can print0.1 + 0.2 = 0.30000000000000004 — both and are already tiny bit rounded when stored, and the rounding errors compound. This isn't a bug in any particular language; it's an unavoidable mathematical consequence of representing infinitely many real numbers with finitely many bits.
A quick word on double precision
Double precision (64-bit) floats use 1 sign bit, 11 exponent bits (bias 1023), and 52 mantissa bits — the same core idea, just with far more range and precision, at double the storage cost. This is the default floating-point type in most programming languages (double in C++/Java, the default float in Python) specifically because 32-bit precision's rounding errors become noticeable too quickly for most real applications.
Minor concept: Binary Coded Decimal (BCD)
BCD stores each decimal digit (0-9) in its own separate 4-bit group, rather than converting the whole number to pure binary. For example, decimal in BCD is0100 0111 (0100 = 4, 0111 = 7) — notice this is different from 's true binary value, . BCD trades some storage efficiency (4 bits can represent 16 values, but BCD only ever uses 10 of them per digit) for making decimal rounding exact, which matters a great deal for financial calculations, where binary floating point's tiny rounding errors are unacceptable in currency amounts.
Minor concept: character codes (ASCII) and parity bits
Text is just another agreed-upon binary code: ASCII maps each character to a 7-bit number (A = 65 = 1000001, a = 97 = 1100001), extended to 8 bits (one full byte) in practice, with the modern Unicode/UTF-8 standard extending this further to represent every language's characters and emoji, while staying backward-compatible with plain ASCII for the first 128 characters.
A parity bit is a single extra bit appended to a group of bits specifically to catch simple transmission errors: even parity sets the extra bit so the total count of 1s in the whole group is even; if a receiver counts an odd number of 1s upon arrival, it knows (without knowing which bit) that something got corrupted in transit. This is a simple, cheap first line of defense against noise, used constantly in memory hardware and serial communication links.
Common mistakes
- Assuming floating point can represent every decimal number exactly. Only a finite, unevenly-spaced set of values is representable — many ordinary decimals like are only ever approximated.
- Forgetting the implicit leading 1. The stored mantissa never includes that leading 1 — it's silently assumed by every IEEE 754-compliant circuit, freeing up one extra bit of real precision.
- Confusing BCD with plain binary. BCD's
0100 0111bit pattern for 47 is not the same as binary 47's actual bit pattern (101111) — BCD is a digit-by-digit encoding, not a base conversion.
Summary
Floating point represents fractional numbers using a binary version of scientific notation: sign, biased exponent, and a normalized mantissa with an implicit leading 1, standardized by IEEE 754 (32-bit single or 64-bit double precision). Because only finitely many bits are available, floating point cannot represent every real number exactly, causing small, unavoidable rounding errors like precisely. BCD offers an alternative for exact decimal-digit storage where floating point's rounding is unacceptable, ASCII/Unicode encode text the same way instructions encode operations (an agreed-upon bit pattern), and parity bits offer a simple, cheap way to detect (not fix) single-bit transmission errors.