How to find a running average from an int that changes every frame
I have an int (ie. external sensor value) that changes every frame. I would like to find a running average over every 10 frames or so, because I am trying to smooth out the occasional erratic values.
What is the simplest way to do this in Unity and how do you store the changing values to calculate an average?
Answer by pako · Feb 10, 2018 at 02:58 PM
To calculate a Moving Average per the "Cumulative moving average" formula in your link, use the following code:
using UnityEngine;
public class AverageValues : MonoBehaviour
{
public int NewValue; //this is an example for the value to be averaged
public int MovingAverageLength = 10; //made public in case you want to change it in the Inspector, if not, could be declared Constant
private int count;
private float movingAverage;
// Update is called once per frame
void Update ()
{
count++;
//This will calculate the MovingAverage AFTER the very first value of the MovingAverage
if (count > MovingAverageLength)
{
movingAverage = movingAverage + (NewValue - movingAverage) / (MovingAverageLength + 1);
//Debug.Log("Moving Average: " + movingAverage); //for testing purposes
}
else
{
//NOTE: The MovingAverage will not have a value until at least "MovingAverageLength" values are known (10 values per your requirement)
movingAverage += NewValue;
//This will calculate ONLY the very first value of the MovingAverage,
if (count == MovingAverageLength)
{
movingAverage = movingAverage / count;
//Debug.Log("Moving Average: " + movingAverage); //for testing purposes
}
}
}
}
I include the necessary code in a separate class AverageValues
for demonstration purposes. Of course you can use the necessary code inside your own class.
Isn't there a typo line 34? I think it's movingAverage = movingAverage / count;
Answer by Commoble · Feb 10, 2018 at 01:34 AM
I would store the changing values in a Queue and calculate the average every frame.
The average of 10 values is trivial to calculate performance-wise, but if you really wanted to optimize it, once you hit 10 values and start taking things out of the queue, instead of taking the average of each value, you could subtract 1/10 of the outgoing value (from ten frames ago) from your running total and add 1/10 of the new incoming value (I can't guarantee this won't cause weird skewing problems from rounding errors if you do this for a long time, though).
for being the right answer.
If you're using integer math, you can get a rounding error after the first frame if you are doing the add or subtract a fraction thing. You could do something weird like store the result of division in one queue and the remainder in another queue then use the result to influence the floating average and use the modulus values to wiggle an error variable that converts over to a plus or $$anonymous$$us one on the running average whenever it gets too large or too small.
...you'll probably never recoup the time it would take to write a "fast", accurate averaging algorithm in terms of execution time, though. ;)
Oh, right, he's working with ints. Yeah, you'd want to convert to floats if you're adding/subtracting from the running total
I tried to type the "plus" in "plus one" as a symbol and it didn't work out very well...
I'm a very beginner programmer. Could you give a short example of what this would look like in C# code? Thank you!
PS. I'm not concerned with small rounding errors. I'm dealing with integers from 0-1024 and simply want to smooth out the occasional extreme outlier number. It is not a super-precise application.
Wouldn't using a Queue be an overkill in this case? I mean why not use just a simple int variable to accumulate all the values to be averaged?
Am I missing something?
Also, @NCartist do you want to average only the last 10 values, or every 10 values average all the available values?
@pako I would like a running / moving average https://en.wikipedia.org/wiki/$$anonymous$$oving_average
Your answer
Follow this Question
Related Questions
how do I make my character jump while running without losing all your speed 1 Answer
[Right Click to Necromance] How I do the run system, for only one character? (FOR 2D RPG GAME) 2 Answers
unity not popening mac suddenly 0 Answers
if the user account does not have a Korean name goes? 0 Answers
Exception: IL2CPP Linkage failed 1 Answer