Fraction to binary conversion is the mathematical process of translating a decimal value between 0 and 1 into a base-2 sequence of bits representing negative powers of two. If you are writing firmware for an ESP32, configuring a digital-to-analog converter (DAC), or calculating pulse-width modulation (PWM) duty cycles, you cannot simply hand the microcontroller a decimal like 0.4545. The hardware requires binary. Understanding how decimal fractions map to binary bits is the difference between a precision power supply and one that drifts by millivolts and triggers undervoltage lockouts.

The Core Mechanism: Multiplying by Two

When converting the integer portion of a number to binary, you repeatedly divide by 2 and record the remainders. For the fractional portion, the process is exactly inverted: you repeatedly multiply by 2 and record the integer part of the result.

The Golden Rule of Fractional Conversion: Multiply the fraction by 2. The whole number (either 0 or 1) becomes your next binary bit. Keep the remaining decimal fraction and repeat until the fraction reaches exactly 0, or until you hit your hardware's bit-depth limit.

Worked Numeric Example: Converting 0.6875

Let us walk through a clean, terminating fraction. We want to convert the decimal 0.6875 to binary.

  1. Step 1: 0.6875 × 2 = 1.375. Record the 1. Keep the 0.375.
  2. Step 2: 0.375 × 2 = 0.75. Record the 0. Keep the 0.75.
  3. Step 3: 0.75 × 2 = 1.5. Record the 1. Keep the 0.5.
  4. Step 4: 0.5 × 2 = 1.0. Record the 1. The fraction is now 0, so we stop.

Reading the recorded bits in order from top to bottom, the binary fraction is 0.1011. You can verify this on the bench by summing the negative powers of two: (1 × 2-1) + (0 × 2-2) + (1 × 2-3) + (1 × 2-4) = 0.5 + 0 + 0.125 + 0.0625 = 0.6875.

Where You Meet Fraction to Binary in Practice

Abstract math becomes physical reality the moment a digital signal crosses into the analog domain. Here is where this conversion dictates your circuit's behavior:

  • DAC Output Voltage Steps: A 12-bit DAC like the Microchip MCP4921 (operating in 12-bit mode) has 4096 discrete steps. If your reference voltage is 3.3V, each binary step represents 3.3 / 4096 = 0.000805V. When you command a specific voltage, your firmware must convert the target fraction into a 12-bit binary string.
  • PWM Duty Cycle Resolution: The ESP32's LEDC peripheral allows you to set PWM resolution up to 20 bits. If you need a 33.3% duty cycle, you are asking the hardware to represent the fraction 0.333... in binary. Because it is a repeating fraction, the hardware truncates it, resulting in a slight timing jitter.
  • ADC Quantization Error: When an analog-to-digital converter samples a voltage, it assigns a binary code to it. The difference between the actual analog voltage and the nearest binary-representable fraction is your quantization error.

The Repeating Fraction Trap (And What It Changes in a Circuit)

In the decimal system, 0.1 is a clean, terminating number. In binary, decimal 0.1 is a repeating fraction: 0.0001100110011... extending into infinity. This is the exact same phenomenon as 1/3 being 0.333... in decimal.

Think of it like trying to perfectly divide a physical 10-inch board into three equal pieces using only a tape measure marked in halves, quarters, and eighths—you will always have a tiny sliver of error left over.

What this changes in a real circuit: If your Arduino or ESP32 firmware relies on standard 32-bit floating-point math to calculate sensor averages or timing intervals using decimal fractions like 0.1, the microcontroller silently truncates that repeating binary sequence. Over thousands of loops, this truncation error accumulates. In a motor control loop, this manifests as a steady-state velocity drift. In a digital power supply, it manifests as a persistent millivolt offset between your target setpoint and the actual output.

Real-World Scenario Walkthrough: The 10-Bit DAC Drift

To see how fraction to binary conversion breaks a physical build, let us look at a programmable bench power supply project.

  • The Setup: You are building a power supply using an Arduino Uno and a 10-bit DAC with a precise 5.000V reference. Your target output for a sensitive analog sensor is exactly 1.000V.
  • The Numbers: To get 1.0V from a 5.0V reference, the required fraction is 1.0 / 5.0 = 0.2. As established, 0.2 is a repeating fraction in binary. A 10-bit DAC can only hold 10 bits. The binary representation of 0.2 truncated to 10 bits is 0011001100, which equals the decimal integer 204.
  • The Outcome: The Arduino sends the 10-bit value 204 to the DAC. The DAC outputs (204 / 1024) × 5.000V = 0.99609V.
  • What Went Wrong: The firmware assumed a clean decimal fraction (0.2) would map cleanly to the hardware register. Instead, the truncation of the repeating binary fraction resulted in a ~3.9mV error. While 3.9mV sounds small, the downstream sensor had an undervoltage lockout threshold of 0.998V. The system refused to boot.
The Fix: Never use floating-point fractions for hardware registers. Use integer math. Calculate the DAC register value directly: (Target_mV * 1024) / 5000. For 1000mV, this is (1000 * 1024) / 5000 = 204.8. You can then intentionally round to 205, yielding 1.0009V, which safely clears the lockout threshold.

Quick Reference and Common Confusions

The most common mistake makers and students make is confusing the integer conversion method with the fractional conversion method. They attempt to divide the fraction by 2, resulting in a mess of decimals that yields no usable bits.

Feature Integer Conversion (e.g., 13) Fraction Conversion (e.g., 0.6875)
Mathematical Operation Divide by 2 Multiply by 2
What to Record The Remainder (0 or 1) The Integer part (0 or 1)
Bit Order Read remainders Bottom-to-Top (LSB to MSB) Read integers Top-to-Bottom (MSB to LSB)
Termination Condition Quotient reaches 0 Fraction reaches 0, or bit-limit hit

Frequently Asked Questions

Can every decimal fraction be converted to an exact binary fraction?
No. Only fractions that can be expressed as a sum of negative powers of two (like 0.5, 0.25, 0.75, 0.125) terminate cleanly in binary. Common decimal values like 0.1, 0.2, and 0.3 result in infinitely repeating binary sequences that must be truncated by your hardware's bit depth.

How does this affect my ESP32's analogWrite() equivalent?
The ESP32 uses the LEDC peripheral for PWM, which takes an integer duty cycle value based on your configured resolution. If you set a 10-bit resolution (0-1023) and want a 50% duty cycle, you pass 511 or 512. If you try to pass a float like 0.5 directly into a function expecting an integer, the C++ compiler will truncate it to 0, giving you a 0% duty cycle and a dead circuit.

What happens if I just round the repeating fraction up?
Rounding up (e.g., turning 204.8 into 205) pushes your output voltage slightly above the target. In precision analog circuits, you must calculate whether rounding up or truncating down keeps you within the acceptable tolerance band of your specific load.