How to calculate simple moving average faster in C?
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
A simple moving average is easy to write, but the obvious implementation does unnecessary work. If you sum the last n values again for every position, the cost grows quickly on large inputs or live streams.
The standard optimization is a sliding window. Instead of recomputing the full sum, keep the current window total, subtract the value that leaves the window, and add the new value that enters it.
Why the Naive Version Is Slow
Suppose you have one million samples and a window size of 100. A naive loop performs roughly 100 additions for each output point. That gives you time complexity of O(count * period).
For a moving average, consecutive windows overlap almost completely. The window for index 10 and the window for index 11 differ by only two values:
- one value drops out on the left
- one value is added on the right
That means the new sum can be derived from the old sum in constant time. With that change, the whole algorithm becomes O(count).
Sliding Window Implementation
The example below uses C# because the existing article tags target that runtime. It returns one average for each full window and throws on invalid input instead of silently producing bad data.
For the sample input, the output is 12, 15.333333333333334, 18.666666666666668, 20, 18.666666666666668. Each number is the average of one consecutive block of three values.
Handling Streaming Data
If values arrive one at a time, you usually do not want to rebuild an array on every update. A queue plus a running sum works well for that case.
This pattern is useful for telemetry, market data, sensor readings, or rolling dashboards. Memory stays bounded by the window size, and each update is still constant time.
Choosing the Right Numeric Type
For most workloads, double is the practical choice. It is fast and usually accurate enough for measurements, statistics, and monitoring. If you are handling money, decimal may be safer because it avoids many binary floating-point rounding surprises, but it is slower.
You should also decide what to return before the first full window exists. Common choices are:
- return an empty result until enough samples arrive
- return nullable values for early positions
- use a shorter warm-up average
The best option depends on whether your consumer expects fixed-length output or only complete windows.
Common Pitfalls
- Recomputing the full sum inside a nested loop. That throws away the main optimization and becomes slow on large datasets.
- Forgetting to subtract the outgoing value. The result will drift upward because the sum keeps growing.
- Using integer division when you want fractional output. In C#,
int / inttruncates. - Ignoring invalid periods such as
0or a value larger than the input length. - Choosing
floatfor convenience when accuracy matters. Repeated additions can accumulate noticeable error.
Summary
- A naive moving average costs
O(count * period). - A sliding window reduces the work to
O(count). - Keep a running sum, add the incoming value, and subtract the outgoing one.
- Use a queue-based version for real-time streams.
- Validate the period and choose
doubleordecimalbased on your precision needs.

