The average filter and the moving average both assign identical weight to every sample they include: the average filter to all \(k\) samples seen so far, the moving average to the \(n\) samples currently inside its window. Equal weighting has a direct consequence: as more samples accumulate, each individual sample matters proportionally less, so a genuinely new measurement has less and less influence on the estimate the more history has piled up. A first-order low-pass filter fixes this by design: instead of counting every included sample equally, it lets the influence of a sample fade away gradually the older it gets, so the most recent measurement always carries a fixed, freely chosen share of the estimate.
A Freely Tunable Recursive Filter
The first-order low-pass filter — also called an exponential moving average or exponential smoothing filter — blends the previous estimate with the newest sample:
\[ \overline{x}_k = (1-\alpha)\,\overline{x}_{k-1} + \alpha\,x_k, \qquad 0<\alpha<1. \]
Unlike the average filter's \(\alpha=\frac{k-1}{k}\), the coefficient \(\alpha\) here is not tied to a sample count: it is a free design parameter chosen once, independent of how many measurements have been taken. A value of \(\alpha\) close to \(1\) puts almost all weight on the newest sample, so the filter tracks quickly but barely smooths; a value close to \(0\) puts almost all weight on the accumulated history, smoothing heavily but responding slowly to a real change.
Why It Is Called Exponential Smoothing
Substituting the same recursion one step earlier,
\[ \overline{x}_{k-1} = (1-\alpha)\overline{x}_{k-2}+\alpha x_{k-1}, \]
into the definition of \(\overline{x}_k\) unrolls one layer of history:
\[ \begin{array}{rl} \overline{x}_k &= (1-\alpha)\overline{x}_{k-1}+\alpha x_{k}\\ &= (1-\alpha)\bigl[(1-\alpha)\overline{x}_{k-2}+\alpha x_{k-1}\bigr]+\alpha x_{k}\\ &= (1-\alpha)^2\overline{x}_{k-2}+\alpha(1-\alpha)x_{k-1}+\alpha x_{k}. \end{array} \]
Since \(0<\alpha<1\), also \(0<1-\alpha<1\), so the coefficient \(\alpha(1-\alpha)\) attached to the older sample \(x_{k-1}\) is strictly smaller than the coefficient \(\alpha\) attached to the newer sample \(x_k\). Repeating the substitution \(n\) times shows the pattern in general:
\[ \overline{x}_k = (1-\alpha)^n\overline{x}_{k-n} + \alpha\sum_{j=0}^{n-1}(1-\alpha)^j x_{k-j}. \]
The weight on a sample \(j\) steps in the past is \(\alpha(1-\alpha)^j\), shrinking geometrically as \(j\) grows — an exponential decay of influence with age, which is exactly why the filter is called exponential smoothing. The weights still add up to exactly \(1\) no matter how far back the recursion is unrolled, since the geometric series telescopes:
\[ (1-\alpha)^n + \alpha\sum_{j=0}^{n-1}(1-\alpha)^j = (1-\alpha)^n + \bigl[1-(1-\alpha)^n\bigr] = 1, \]
so the output is always a genuine weighted average of the current and all past samples, never an over- or under-count.
Time Constant and Cutoff Frequency
The name "low-pass filter" is not a metaphor: this recursion is the direct digital counterpart of the classical analog RC low-pass filter. A resistor \(R\) and a capacitor \(C\) in series obey, by Kirchhoff's voltage law,
\[ \tau\,\dot{y}(t)+y(t)=x(t), \qquad \tau := RC, \]
where \(\tau\) is the circuit's time constant. Approximating the derivative over a small sampling interval \(dt\) by a forward difference, \(\dot{y}(t)\approx\frac{y_k-y_{k-1}}{dt}\), turns this continuous equation into
\[ \tau\,\frac{y_k-y_{k-1}}{dt}+y_{k-1}=x_k \quad\Longrightarrow\quad y_k = \Bigl(1-\frac{dt}{\tau}\Bigr)y_{k-1}+\frac{dt}{\tau}x_k. \]
Matching coefficients with the recursive filter identifies
\[ \alpha = \frac{dt}{\tau} \quad\Longleftrightarrow\quad \tau = \frac{dt}{\alpha}, \]
valid whenever \(dt\ll\tau\), i.e. whenever \(\alpha\ll1\) — comfortably true for the values used in practice below. A first-order lag with time constant \(\tau\) has the standard \(-3\,\)dB cutoff frequency \(f_c=\frac{1}{2\pi\tau}\), so
\[ f_c \approx \frac{\alpha}{2\pi\,dt}. \]
This gives a direct way to pick \(\alpha\) for a target cutoff frequency, or to check what cutoff frequency a chosen \(\alpha\) implies, without needing any further frequency-domain analysis.
Tuning by Step Response
A second, purely time-domain way to characterize the filter needs no frequency-domain reasoning at all: measure how many samples it takes to react to a sudden change. Suppose the filter has settled at \(\overline{x}_0=1\) because the input has held steady at \(1\) for a long time, and the input then drops to \(x_k=0\) from \(k=1\) onward. Each step multiplies the current estimate by \((1-\alpha)\):
\[ \overline{x}_1=(1-\alpha),\quad \overline{x}_2=(1-\alpha)^2,\quad \dots,\quad \overline{x}_n=(1-\alpha)^n. \]
Setting this equal to a target ratio \(\rho\) and solving for \(n\) gives the number of samples, and hence the time \(T=n\,dt\), needed to fall to that fraction of the original value:
\[ (1-\alpha)^n=\rho \quad\Longrightarrow\quad n = \frac{\ln\rho}{\ln(1-\alpha)}. \]
Three ratios are commonly used as reference points: the \(-3\,\)dB point \(\rho=\frac{1}{\sqrt2}\approx0.7071\) (half power), the \(-6\,\)dB point \(\rho=\frac12\) (a quarter power, a more aggressive noise-suppression target), and \(\rho=\frac1e\approx0.3679\), which marks the time constant \(\tau\) itself.
Worked Example: \(dt=10\,\)ms
Writing \(\alpha=\frac1k\) turns the free parameter into a single integer "damping number" \(k\), the same convenient parametrization used for the average filter, though here \(k\) is chosen directly rather than growing with the sample count. Take a control loop sampling every \(dt=10\,\)ms and compare \(k=20\) (\(\alpha=0.05\)) against \(k=50\) (\(\alpha=0.02\)):
| \(k\) | \(\alpha\) | \(-3\,\)dB | \(-6\,\)dB | \(1/e\ (\approx\tau)\) | \(f_c\) |
|---|---|---|---|---|---|
| \(20\) | \(0.05\) | \(n=7\), \(T=70\,\)ms | \(n=14\), \(T=140\,\)ms | \(n=20\), \(T=200\,\)ms | \(0.80\,\)Hz |
| \(50\) | \(0.02\) | \(n=18\), \(T=180\,\)ms | \(n=35\), \(T=350\,\)ms | \(n=50\), \(T=500\,\)ms | \(0.32\,\)Hz |
Two things are worth noticing. First, the \(1/e\) column matches \(\tau=dt/\alpha=k\,dt\) almost exactly (\(200\,\)ms and \(500\,\)ms), confirming the continuous-time analogy above: with \(\alpha=\frac1k\), the time constant is simply \(k\) sampling intervals. Second, the cutoff frequency computed from \(f_c\approx\frac{\alpha}{2\pi\,dt}\) is far below the value obtained by naively taking the reciprocal of the \(-3\,\)dB settling time (\(1/70\,\text{ms}\approx14\,\)Hz): the settling time and the cutoff frequency are related but distinct quantities, and only the \(\frac{\alpha}{2\pi\,dt}\) formula gives the actual frequency-domain cutoff.
This gap matters in practice. Consider a self-balancing two-wheeled vehicle that samples its tilt sensor every \(dt=10\,\)ms and needs the filtered tilt to still reflect a genuine sway of the chassis, which for such vehicles typically happens around \(1\,\)Hz. With \(k=20\) (\(f_c\approx0.80\,\)Hz), that sway sits close to the cutoff and still comes through only mildly delayed, so the balance controller keeps up, at the cost of somewhat noisier readings. With \(k=50\) (\(f_c\approx0.32\,\)Hz), the same \(1\,\)Hz sway lies well inside the stop-band and gets smoothed away almost entirely: the controller reacts far too late to a real tilt, and the vehicle can topple over precisely because the filter is doing its job of rejecting anything faster than its cutoff — including the disturbance the controller actually needed to see. Choosing \(k\) is therefore a genuine trade-off between rejecting sensor noise and staying fast enough to track the dynamics the controller has to react to.
Software Implementation
Translating the recursion directly into code needs only the smoothing coefficient and the previous output:
function LowPassFilter(alpha) {
let xp = null // no previous estimate yet
return function (xk) {
xp = (xp === null) ? xk : (1 - alpha) * xp + alpha * xk
return xp
}
} Initializing xp to the first real reading, rather than to an arbitrary constant such as \(0\), matters: seeding the filter with a value far from the true signal would show up as an exponentially decaying startup transient riding on top of every following output, exactly the kind of artifact the filter is supposed to remove. Assigning the first sample directly sidesteps that transient entirely.
Hardware Realization
The discretization above works in reverse, too: the same first-order lag can be built directly in analog hardware from a single resistor \(R\) and capacitor \(C\) forming a voltage divider, giving the transfer function
\[ H(s)=\frac{1/(sC)}{R+1/(sC)}=\frac{1}{1+sRC}, \]
the continuous-time low-pass with time constant \(\tau=RC\) and cutoff \(f_c=\frac{1}{2\pi RC}\) used above. Picking, for instance, \(C=100\,\)nF and targeting the \(f_c\approx0.80\,\)Hz cutoff from the \(k=20\) example gives
\[ R = \frac{1}{2\pi f_c C} \approx 2\,\text{M}\Omega. \]
If the filtered signal has to drive a load with non-negligible current, such as a small speaker or the input of another circuit stage, that load's own resistance changes the effective \(R\) and shifts the cutoff. A single transistor wired as an emitter follower, needing only one additional resistor at its emitter, buffers the RC filter from the load without drawing current through it, keeping the cutoff frequency where the RC values say it should be.
The filter is easy to hear as well as see: feeding music into an RC low-pass and comparing the input and output on an oscilloscope shows the higher-frequency content — cymbals, sibilants, overall brightness — visibly and audibly softened, while the lower-frequency content passes through largely unchanged; swapping in a larger capacitor lowers the cutoff further and makes the effect more pronounced.
Demonstration
Simulated ultrasonic distance readings, oscillating between a near and a far object with added noise, show the trade-off directly: a faster filter (\(\alpha=0.3\), orange) tracks the true distance closely but still shows visible noise, while a slower filter (\(\alpha=0.05\), red) is much smoother but visibly lags behind at every rise and fall.
Key Results
- The first-order low-pass filter \(\overline{x}_k=(1-\alpha)\overline{x}_{k-1}+\alpha x_k\) gives every sample a weight \(\alpha(1-\alpha)^j\) that decays geometrically with its age \(j\), rather than the equal weighting used by the average filter or the moving average.
- Unlike the average filter's \(\alpha=\frac{k-1}{k}\), the coefficient \(\alpha\) here is a free, fixed design parameter, not tied to a sample count.
- The recursion is the exact digital counterpart of the analog RC low-pass: discretizing \(\tau\dot y+y=x\) gives \(\alpha=\frac{dt}{\tau}\) and the cutoff frequency \(f_c\approx\frac{\alpha}{2\pi\,dt}\).
- The number of samples needed for a step disturbance to fall to a target fraction \(\rho\) is \(n=\frac{\ln\rho}{\ln(1-\alpha)}\); the \(1/e\) case reproduces the time constant \(\tau\approx k\,dt\) when \(\alpha=\frac1k\), but this settling time is not the same quantity as the cutoff frequency and must not be inverted directly to estimate it.
- Seeding the filter's first output with the first real sample, rather than an arbitrary constant, avoids an exponentially decaying startup transient.
- The same first-order lag can be built from a single resistor and capacitor, optionally buffered by a single-transistor emitter follower when driving a load.