# Calculating a Running Average

In a newsgroup I replied to a question about calculating average data throughput during data reception over the network. A simple average bytes per second calculation needs only a few lines of code:

``````int bytesTotal = 0;
int bytesPerSecond = 0;
DateTime startTime = DateTime.Now;

do {
bytesPerSecond = bytesTotal / (DateTime.Now - startTime).TotalSeconds;

...
``````

The problem with this is that it may not render very exact values over a longer download period because actual network throughput tends to change a lot over WAN connections. It would be more accurate to work out an average over a number of most recent measured values instead. As this requires some handling of a store of measured samples, I decided to create a reusable class that can hold a number of samples in a ring buffer and calculate the current average from these samples. The class takes a weighting of each sample into account, because in scenarios like the one above it’s not always guaranteed that new samples can be measured in an exact frequency. Here’s the class:

``````public class RunningAverage {
public RunningAverage(int samplesCount) {
samples = new Sample[samplesCount];
for (int i = 0; i < samplesCount; i++)
samples[i] = new Sample( );
currentSample = 0;
}

class Sample {
public Sample( ) { }

public Sample(double weighting, double measuredValue) {
Set(weighting, measuredValue);
}

public void Set(double weighting, double measuredValue) {
this.weighting = weighting;
this.measuredValue = measuredValue;
isValid = true;
}

private double weighting;
public double Weighting { get { return weighting; } }

private double measuredValue;
public double MeasuredValue { get { return measuredValue; } }

private bool isValid;
public bool IsValid { get { return isValid; } }
}

Sample[] samples;
int currentSample;

public void AddSample(double weighting, double measuredValue) {
samples[currentSample++].Set(weighting, measuredValue);
if (currentSample >= samples.Length)
currentSample = 0;
}

public double GetCurrentAverage( ) {
double totalValue = 0;
double totalWeighting = 0;
foreach (Sample sample in samples)
if (sample.IsValid) {
totalValue += sample.MeasuredValue;
totalWeighting += sample.Weighting;
}
}
}
``````

Now the receive loop above could look like this:

``````RunningAverage average = new RunningAverage(100);
DateTime timeStamp = DateTime.Now;

do {
DateTime newTimeStamp = DateTime.Now;