Search code examples
phparraysmedian

Calculating Median of an array in PHP


I'm trying to figure out how to calculate the median of an array of randomly generated numbers. I have the array all set up, but I'm having trouble putting together a function for the calcuation.

This is what I have so far:

//array 
$lessFifty = array();
$moreFifty = array();

//number generation
for ($i = 0; $i<=30; $i++) {
      $number = rand(0, 100);

//Sorting <50>      
if ($number < 50 ) {
    $lessFifty[] = $number;
} else {
    $moreFifty[] = $number; 
   } 
}
 echo print_r($lessFifty); 
 echo "<br>" ;
 echo print_r($moreFifty);

   //Average
echo "<p> Average of values less than fifty: </p>";
    print   array_sum($lessFifty) / count($lessFifty) ;
echo "<p> Average of values greater than fifty: </p>" ;  
    print   array_sum($moreFifty) / count($moreFifty) ;

//Median
$func = function (median ($array, $output = $median)){ 
    if(!is_array($array)){
        return FALSE;
    }else{
        switch($output){
                rsort($array);
                $middle = round(count($array) 2);
    $total = $array[$middle-1];
        break; 
    return $total;
    }
}

echo $func ; 

I'm pretty sure that I'm doing this median section completely wrong. I'm just learning and its proving to be a challenge.


Solution

  • Be careful about how you write your for() loop. If you want 30 entries, then you should not use <= or you will end up with 31 because $i starts with 0.

    Build an array of the random numbers, then sort them.

    Then determine if you have a central entry (odd array length) or if you need to average the middle two entries (even array length).

    Here is a modern implementation of a median method posted in 2022 on CodeReview.

    Code: (Demo)

    $limit = 30;  // how many random numbers do you want?  30 or 31?
    for ($i = 0; $i < $limit; ++$i) {
        $numbers[] = rand(0, 100);
    }
    var_export($numbers);
    
    //echo "\n---\nAverage: " , array_sum($numbers) / $limit;
    echo "\n---\n";
    
    sort($numbers);
    $count = count($numbers);   // cache the count
    $index = intdiv($count, 2);  // cache the index
    if (!$count) {
        echo "no values";
    } elseif ($count & 1) {    // count is odd
        echo $numbers[$index];
    } else {                   // count is even
        echo ($numbers[$index-1] + $numbers[$index]) / 2;
    }
    

    Possible Output:

    array (
      0 => 27,
      1 => 24,
      2 => 84,
      3 => 43,
      4 => 8,
      5 => 51,
      6 => 60,
      7 => 86,
      8 => 9,
      9 => 48,
      10 => 67,
      11 => 20,
      12 => 44,
      13 => 85,
      14 => 6,
      15 => 63,
      16 => 41,
      17 => 32,
      18 => 64,
      19 => 73,
      20 => 43,
      21 => 24,
      22 => 15,
      23 => 19,
      24 => 9,
      25 => 93,
      26 => 88,
      27 => 77,
      28 => 11,
      29 => 54,
    )
    ---
    43.5
    

    After sorting, elements [14] and [15] hold 43 and 44 respectively. The average of these "middle two" values is how the result is determined. (Hardcoded numbers demo)


    If you want a short, inflexible, hardcoded snippet, then you can use 30 and 14 and 15 as your predetermined size and indexes.

    for ($i = 0; $i < 30; ++$i) {
        $numbers[] = rand(0, 100);
    }
    sort($numbers);
    echo ($numbers[14] + $numbers[15]) / 2;