How to calculate the average progressively without know the total items?

1.5k views Asked by At

(Language PHP - This question is for any language, particularly I'm using PHP) For example you have an array of numbers like:

$q = array( 1, 2, 3, 4, 5, ... ); // ... mean you can give more numbers
$i = 0;
$currentAverage = 0;
while ($i < count( $q )) {
    $currentAverage = ($currentAverage + $q[$i]) / 2;  // this is my try
    $i++;
}

echo "The final average is: " . $currentAverage . "<br/>";

Obviusly, you can divide by count( $q ) the sum, but that's not the idea.

I hope you can help me! thanks.

2

There are 2 answers

0
Mulan On

You can't calculate an "incremental" mean average without knowing the total number of items make up that average.

For example, if you have 10 items that average 5 and you want to add the next item, X, you have to give the appropriate "weight" to the newly added item.

For example, to get the next average, you would do

(currentAverage * currentNumberOfItems + X) / (currentNumberOfItems + 1)

If we say X is 7, the new average would be

(5 * 10 + 7) / (10 + 1)
= (50 + 7) / 11
= 57 / 11
= 5.181818182

It is impossible to do this calculation without knowing the current number of items that make up the average (10) beforehand


To show you this working in an incremental fashion, here is a for loop that keeps track of the average as the loop is running

$xs = [1,2,3,4,5];
$average = $xs[0];
for ($count = 1; $count < count($xs); $count++) {
  echo sprintf("average: %0.3f, count: %d" . PHP_EOL, $average, $count);
  $average = ($average * $count + $xs[$count]) / ($count + 1);
}

average: 1.000, count: 1
average: 1.500, count: 2
average: 2.000, count: 3
average: 2.500, count: 4
0
CUGreen On

Could use this:

$q = array( 1, 2, 3, 4, 5, ... ); // ... mean you can give more numbers
$i = 0;
$currentAverage = 0;
while ($i < count( $q )) {
    $sliceArr = array_slice($q, 0, $i+1);
    $currentAverage = array_sum($sliceArr) / count($sliceArr);
    $i++;
}

echo "The final average is: " . $currentAverage . "<br/>";