Calculating Median of an array in PHP
Asked Answered
G

2

7

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.

Garrek answered 20/9, 2018 at 23:11 Comment(0)
A
13

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;
Averill answered 20/9, 2018 at 23:23 Comment(6)
Oh, then $i should be equal to one I believe.Garrek
If this was my project, I'd leave as 0 and change the comparison from <= to <. It doesn't really matter though, because sort() will refresh the indexes anyhow.Averill
I understand most of this, but what does the ! in the (!$count) part specifically DO?Garrek
It is a falsey check. When count() (aka sizeof()) returns a 0 result, the ! will catch it and evaluate the condition to be true. I could have also written it as if ($count == 0) { or if ($count === 0) { or if ($count < 1) {. I chose the shortest syntax.Averill
Sorry, I'm having a hard time finding the right words for some of my inquiries since I'm new to coding altogether. I went ahead and completed the tour. Thanks for your help! I'll try to improveGarrek
We were all like you once. Truth is, I learn new techiques and terminology all the time as I research and help others with issues. As you search for existing solutions, you will discover new words that will help you to continue searching and/or post an articulate question. Good luck.Averill
P
0

I like this function because I find it very readable and the logic is easy to follow:

function calculateMedian($array) {
    if (empty($array)) {
        return null;
    } else {
        sort($array);
        $length = count($array);
        $middle_index = floor(($length - 1) / 2);
        if ($length % 2) {
            return $array[$middle_index];
        } else {
            $low = $array[$middle_index];
            $high = $array[$middle_index + 1];
            return ($low + $high) / 2;
        }
    }
}

Alternatively, this function is a little more concise but less readable:

function calculateMedian($array) {
    if (empty($array)) {
        return null;
    } else {
        sort($array);
        $lowMiddle = $array[floor((count($array) - 1) / 2)];
        $highMiddle = $array[ceil((count($array) - 1) / 2)];
        return ($lowMiddle + $highMiddle) / 2;
    }
}
Pansypant answered 29/6, 2023 at 13:34 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.