0

I need to calculate the average of only the 10 most recent float values in a method being called every frame with the float values constantly changing.

If I have the following

1- Would I correctly be getting the average value of the 10 most recent floats?

Thanks!

List<float> floatVals= new List<float> { };
Update(){

floatVals.Add(myChangingFloatVal);

if(floatVals.Count>=10){
floatVals.RemoveRange(0, 1);
_averageFloat= floatVals.Average();

}
Bachalo
  • 6,965
  • 27
  • 95
  • 189

1 Answers1

0

I would prefer to have a list outside of your average method. Also, i do not see where your changingFloatValue changes in your example. The for loop shown will push the same value into the list 10 time, average being the same as the value. Consider changing to something like this.

// Max number of values to average
//
private int maxAverageValues = 10;

// Running list of values to average
//
private List<float> valuesToAverage = new List<float>();

private float AddValueGetAverage(float newValue)
{
    // New values are added to the end of the list
    //
    valuesToAverage.Add(newValue);
    
    // Check if we exceeded the max amount of values we want to average
    //
    if (valuesToAverage.Count > maxAverageValues)
    {
        // Max exceeded, remove the oldest value
        //
        valuesToAverage.RemoveAt(0);
    }

    // Return the average
    //
    return valuesToAverage.Sum() / valuesToAverage.Count;
}

EDIT

As per Amys suggestion, here is the same code using Queue instead of List.

Per Microsofts documentation: Objects stored in a Queue are inserted at one end and removed from the other. Queues and stacks are useful when you need temporary storage for information; that is, when you might want to discard an element after retrieving its value. Use Queue if you need to access the information in the same order that it is stored in the collection.

private int maxValuesForFloatingAverage = 10;
private Queue<float> floatingAverageValues = new Queue<float>();

private float changingFloat = 0f;
private float changingFloatAvg = 0f;

void Update()
{
    // update the changing float value here...

    // Enqueue the new value
    //
    floatingAverageValues.Enqueue(changingFloat);

    // Check if we exceeded the amount of values we want to average
    //
    if (floatingAverageValues.Count > maxValuesForFloatingAverage)
    {
        // Max exceeded, dequeue the oldest item
        //
        floatingAverageValues.Dequeue();
    }

    // Take the average
    //
    changingFloatAvg = floatingAverageValues.Sum() / floatingAverageValues.Count;
}
hijinxbassist
  • 3,667
  • 1
  • 18
  • 23
  • 2
    Since you're adding to the end of the list, and removing from the beginning, a `Queue` could be used instead. See https://stackoverflow.com/questions/10380692/queuet-vs-listt –  Mar 11 '21 at 21:26
  • @Amy Very true, cool suggestion. Since this is being used as a queue, i do see the benefit of clearly showing intent. Speed wont be much of an issue here, but that is also another reason to use queue over list. Good suggestion. – hijinxbassist Mar 11 '21 at 21:30
  • Thanks for the quick reply. I edited my question to remove the for loop. – Bachalo Mar 11 '21 at 21:31