A fraction decimal to binary conversion is the mathematical process of translating a base-10 fractional value (like 0.6875) into a base-2 sequence of bits after the radix point (like 0.1011) by repeatedly multiplying the fractional remainder by 2. While integer binary conversion is second nature to most embedded developers, fractional conversion is the hidden math that dictates the actual physical voltage steps your microcontroller can output or measure.
The Core Mechanism: Multiplying by Two
When you convert a whole number to binary, you repeatedly divide by 2 and record the remainders. Fractions require the exact opposite approach: you repeatedly multiply by 2 and record the integer carry. Think of binary fractions like a set of nesting measuring cups that only come in exact halves: 1/2 cup, 1/4 cup, 1/8 cup. You can perfectly measure 0.75 (1/2 + 1/4), but you can never perfectly measure 1/3 cup without spilling over or coming up short.
Let's walk through a worked numeric example converting the decimal fraction 0.6875 into binary.
- Multiply by 2: 0.6875 × 2 = 1.375. The integer part is 1. Keep the fractional part (0.375).
- Multiply by 2: 0.375 × 2 = 0.75. The integer part is 0. Keep the fractional part (0.75).
- Multiply by 2: 0.75 × 2 = 1.50. The integer part is 1. Keep the fractional part (0.50).
- Multiply by 2: 0.50 × 2 = 1.00. The integer part is 1. The fractional part is 0, so we stop.
Reading the integer carries from top to bottom, we get 0.1011. Therefore, 0.6875 in decimal equals 0.1011 in binary.
Because the fractional part eventually hit exactly zero, this is a 'terminating' binary fraction. As we will see in the real-world scenario below, not all decimal fractions are so cooperative.
Where You Meet This in Practice
You encounter binary fractions whenever an embedded system bridges the gap between continuous analog physics and discrete digital logic. Specifically, this math governs three core peripherals:
- Analog-to-Digital Converters (ADC): When an ESP32 samples a 1.8V analog signal on GPIO34 against a 3.3V reference, the internal SAR (Successive Approximation Register) ADC is essentially testing binary fractions (1/2, 1/4, 1/8 of 3.3V) to find the closest match.
- Digital-to-Analog Converters (DAC): True DACs, like the 8-bit DAC on the Arduino Due or the 12-bit DACs on the STM32F4, output voltages by summing binary-weighted current sources.
- PWM Duty Cycles: When you call
analogWrite(pin, 127)on an 8-bit PWM register, you are commanding a binary fraction (127/255, or roughly 0.498) of the supply voltage as an average DC output.
What people commonly confuse it with: Hobbyists frequently confuse fractional binary conversion with integer binary conversion (which uses division by 2). More dangerously, they confuse raw binary fractions with IEEE 754 floating-point representation. When your Arduino uses a float variable, it is not storing a simple binary fraction with a radix point; it is storing a sign bit, an 8-bit exponent, and a 23-bit mantissa. Raw binary fractions apply to the hardware registers (ADC/DAC/PWM), while IEEE 754 applies to the CPU's math coprocessor.
Real-World Scenario Walkthrough: The Audio DAC Glitch
To see why terminating vs. repeating binary fractions matter on the bench, let's look at a common pitfall when building custom waveform generators.
The Setup: You are building a simple 8-bit R-2R resistor ladder DAC on a breadboard using a 74HC595 shift register driven by an Arduino Uno. Your goal is to generate a clean 1kHz sine wave for an audio project. The R-2R ladder is powered by the Uno's 5V VCC pin. To synthesize the sine wave, your code calculates the required voltage for each sample and sends the corresponding 8-bit binary byte to the shift register.
The Numbers: At a specific point in the sine wave calculation, your math requires an output of exactly 1.666V, which is 0.3333 (one-third) of your 5V VCC. You need to convert the decimal fraction 0.3333 to an 8-bit binary fraction to send to the DAC.
Let's run the multiplication algorithm:
0.3333 × 2 = 0.6666 (Carry 0)
0.6666 × 2 = 1.3332 (Carry 1)
0.3332 × 2 = 0.6664 (Carry 0)
0.6664 × 2 = 1.3328 (Carry 1)
The pattern 01 repeats infinitely. The true binary representation of 1/3 is 0.010101010101... extending forever.
The Outcome: Because your 74HC595 shift register only accepts 8 bits, your code truncates the fraction to 0.01010101. When you probe the DAC output with an oscilloscope, the sine wave looks visibly 'stepped', and when amplified through a speaker, there is a harsh, buzzy distortion in the audio.
What went wrong: The truncation introduced a quantization error. The 8-bit binary fraction 0.01010101 equals exactly 0.33203125 in decimal.
Target voltage: 0.33333 × 5V = 1.6666V
Actual DAC output: 0.33203125 × 5V = 1.6601V
The hardware is outputting a voltage that is 6.5mV lower than your math requested. In an 8-bit audio system, a 6.5mV error on a 5V scale represents nearly a full Least Significant Bit (LSB) of error, which manifests as audible quantization noise. According to All About Circuits' guide on ADC resolution, this inherent stepping is the primary limiting factor in low-bit-depth digital audio.
Resolution Limits and Quantization Error
The table below illustrates how different decimal fractions behave when forced through an 8-bit hardware register (like an 8-bit PWM timer or DAC). Notice how 'clean' decimal numbers in base-10 often become messy, repeating fractions in base-2.
| Target Decimal Fraction | True Binary Fraction | 8-Bit Truncated Binary | Actual Decimal Value | Voltage Error (at 5V VCC) |
|---|---|---|---|---|
| 0.5000 (1/2) | 0.1 | 0.10000000 | 0.50000000 | 0.00 mV (Exact) |
| 0.2500 (1/4) | 0.01 | 0.01000000 | 0.25000000 | 0.00 mV (Exact) |
| 0.1000 (1/10) | 0.000110011... | 0.00011001 | 0.09765625 | 11.72 mV |
| 0.3333 (1/3) | 0.01010101... | 0.01010101 | 0.33203125 | 6.35 mV |
| 0.8000 (4/5) | 0.11001100... | 0.11001100 | 0.79687500 | 15.62 mV |
FAQ: Binary Fractions in Embedded Systems
Why do some decimal fractions terminate in binary while others repeat?
A fraction terminates in base-2 only if its denominator (when reduced to lowest terms) is a power of 2 (e.g., 2, 4, 8, 16). Therefore, 1/2 (0.5), 1/4 (0.25), and 3/8 (0.375) terminate perfectly. Fractions with denominators that are multiples of 5 or 3 (like 1/10 or 1/3) will repeat infinitely in binary, just as 1/3 repeats infinitely in base-10 decimal (0.333...).
How does the ESP32 handle fractional math compared to an Arduino Uno?
The Arduino Uno (ATmega328P) lacks a hardware Floating Point Unit (FPU). When you use float variables to calculate PWM duty cycles, the AVR CPU performs IEEE 754 math via slow software emulation, which takes hundreds of clock cycles. The SparkFun PWM tutorial highlights how this overhead can cause timing jitter in fast control loops. The ESP32, however, features a dedicated hardware FPU and 32-bit registers. It calculates the IEEE 754 float instantly, but remember: once that float is cast to the ledcWrite() function's duty parameter, it is still truncated to a raw binary fraction (up to 20 bits on the ESP32's LEDC peripheral) before hitting the physical pin.
Can I avoid repeating fraction errors by changing my voltage reference?
No. The repeating nature of the fraction is a mathematical property of base-2, not a property of the voltage. However, you can mitigate the physical impact of the error by increasing your bit depth. Moving from an 8-bit DAC (256 steps) to a 16-bit DAC (65,536 steps) reduces the LSB voltage from 19.53mV down to 0.076mV, pushing the quantization error below the noise floor of most hobbyist op-amps.






