views:

72

answers:

5

Hi! I have to report average value of incoming numbers, how i could do that without using some sort of data structure to keep track of all values and then calculating average by summing them and dividing by number of values?

+1  A: 

keep current sum and count. Update both on every incoming number.

avg = sum / count.

ob1
It could be one simple solution, but i cant use this simple method because of limited precision of floating point numbers - i have huge count of numbers incoming every second so sum would become very large number and some floating point errors will occur...
Oscar
@Oscar: you should specify this restriction in your question, then. As it stands, your question isn't very complicated!
Dan Puzey
@Dan: That's a well-known problem with averaging floating-point numbers and should be considered nearly always when you sum large amounts of numbers.
Joey
You can also keep current avg and count, and do new_avg = (old_avg*old_count + incoming) / (old_count + 1)
ob1
@ob1: so you're doing exactly the same, just with an added multiplication.
Joey
@Johannes: Oh, right ... oops :-)
ob1
I know it's *well-known*, but the OP didn't specify anything about "large amounts" of numbers.
Dan Puzey
+1  A: 

Just keep running sum and how many numbers you have received, that's all you need to compute the average.

dcp
+1  A: 

If you have the numbers a[1] a[2] ... a[n] and you know their average is avg(n) = (a[1] + ... + a[n]) / n, then when you get another number a[n + 1] you can do:

avg(n + 1) = (avg(n) * n + a[n + 1]) / (n + 1)

Some floating point errors are unavoidable, but you should test this and see if it's good enough.

To avoid overflow, you could do the division first:

avg(n + 1) = (avg(n) / (n + 1)) * n + (a[n + 1] / (n + 1))

IVlad
+1  A: 

If I'm not totally mistaken, one could calculate the avg(n+1) also this way:

avg(n+1) = (a[1]+ ... + a[n+1]) / (n+1) = 
         = (a[1]+ ... + a[n])/(n+1)   +   a[n+1]/(n+1) = 
         = (n(a[1]+ ... + a[n])/n) / (n+1) + a[n+1]/(n+1) =
         = n*avg(n) / (n+1) + a[n+1]/(n+1) = 

         = n/(n+1) * avg(n) + a[n+1]/(n+1)

so multiply the old avg by n/(n+1) and add the new element divided by n+1. Depending on how high n will get and how big your values are, this could reduce rounding errors...

EDIT: Of course you have to calculate n/(n+1) using floats, otherwise it will always render 0...

king_nak
A: 

you don't need to keep track the total sum, only counter:

class Averager {
   float currentAverage;
   size_t count;
   float addData (float value) {
       this->currentAverage += (value - this->currentAverage) / ++count;
       return this->currentAverage;
   }
}

from-> http://stackoverflow.com/questions/3316261/prevent-long-running-averaging-from-overflow

uray