Skip to content

Instantly share code, notes, and snippets.

@numberoverzero
Created January 21, 2014 08:36
Show Gist options
  • Save numberoverzero/8536341 to your computer and use it in GitHub Desktop.
Save numberoverzero/8536341 to your computer and use it in GitHub Desktop.
rolling average of a float for a given duration + resolution
public class RollingAverage {
private float resolution;
private float remainderDt;
private float remainder;
private float[] samples;
private int nsamples;
private int oldest;
private float rollingAverage;
public RollingAverage(float duration, int samples) {
this.samples = new float[samples];
nsamples = samples;
resolution = duration / samples;
}
private void advance() {
rollingAverage -= samples[oldest] / nsamples; // Remove oldest from rolling avg
samples[oldest] = remainder; // Store newest sample in place of oldest
rollingAverage += samples[oldest] / nsamples; // Apply newest sample to rolling avg
oldest = (++oldest) % nsamples; // Advance oldest pointer;
remainder = remainderDt = 0; // Reset remainder
}
public void update(float v, float stepDt) {
float stepWeight, delta = remainderDt + stepDt;
while(delta >= resolution) {
delta -= resolution;
stepWeight = resolution - remainderDt; // Amount of this dt needed
// to complete a sample
remainder = ( // Weighted average of remainder from
(remainder * remainderDt) // previous step and partial value
+ (v * stepWeight)) // from current step. Total weight
/ resolution; // equals single sample resolution
advance(); // Store the new sample and update rolling
}
remainder = ( // When we enter the above loop at least once,
(remainder * remainderDt) // remainder and remainderDt will both be 0
+ (v * (delta - remainderDt))) // and this simplifies to:
/ delta; // (0 + v * delta) / delta = v
remainderDt = delta; // When we don't enter the loop, it becomes a
// simple weighted average:
// (delta - remainderDt)
// = (remainderDt + stepDt - remainderDt)
// = stepDt
// remainder = (
// (remainder * remainderDt)
// + (v * stepDt)
// / (remainderDt + stepDt);
}
public float getAverage() {
float partialSample = ( // Still need to include
(remainder * remainderDt) // the remainder, by
+ (samples[oldest] * (resolution - remainderDt))) // weighted averaging
/ resolution; // with oldest sample.
float correction = (partialSample - samples[oldest]) / nsamples; // Delta between partial
// and oldest, scaled
return rollingAverage + correction; // to number of samples
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment