nfTlWNl rn Ѻq$³*%yNk9S maq ƿfX5O&B CӝINgS ^4y[`dJ otYG)g_\`Lٔ*ܝIc3ٿ ZmW6_|m"X0YVY }Jyk;D!ud9ՙ^7? '4SQ[MfEJU۰=;.Ӱ#T,Xظ^(\Opd9kgLzҥ,blUsvs|c̩}kT#L؀Cr2qGp,册}nKˇߖ=3"eo%qZ|wL1UCAPPG:A9͍U4cw2|wĥbrĮf$G+sNTrrdZf %+kihR8 Y6MG4s)._"_PkȽg2YkP3 9KB!d.9-\m9l^1$om2#9@4Ca&2лΣNc9Я<DΆi7aEbCɃIY~(M'G+XY}G-Hi'W{oay_!?dvׅI]t|* iS@!IѲu $9C=;|@uȠ&~x"C͊;|XXbN@d-T/[FDj1pxHy{ѐ$ajNR X\v6:Yh ɣ)<2UJ3Iz2E;U>}f7[^Uٺʚ@lwWN MC>.2f! P|E%Уq˅5;op꿥oqRZ#cuN xj2Zg9sU9'8g~TU? +_t [H@:^,ȺoaxR#ѩTە;ӌh2%Cil17%w,q5jx7fTB uDH{߰k Oq@ oD択H/ӷߡ}:V\fQL[)7s39嬢WKd03'JvƧT)?j @BSst!Yw~~#Acpċ٬oݩ2̘=PHjBu>rWD PvyN9 at(Е,e s+YP5U*86`U4cw2|wĥ%,gP4h#>!i1ս4s \n˃]*ʴZ(pDnD%ÍF i F>w/q[9S'8r;C!b/وjjbδC VdP<.ThR^#v!@VZ_?_YޮU,ZGVQqZ<)5yڂKnxF 'Uzh՗O W5ryhCYzZO2s]C -ⵑ[~?~Y10!3pG5}<b>1DAt5trԖ.F.BU)R;vx%jl!>oݾ B11C3*a]*`zy^h&qn%EʺU!k8T,=tM^||fWIc+|1tWlE BTrQ,d/A%HmY'r7jbBRrqܘu?78q/6S"E(vyEơQ6!7K9?n0BZe@_WOumbS_Ad>[omZ`qLv6|k6I :o]4m@ۻUiΗ`fC(UB$qg8'0;Q<6Y1NDZn+H)OJ!r$cl&N SB9q,M'̐K~numbers. The median is the number in the middle of a set of numbers. * * Excel Function: * MEDIAN(value1[,value2[, ...]]) * * @param mixed ...$args Data values * * @return float|string The result, or a string containing an error */ public static function median(...$args) { $aArgs = Functions::flattenArray($args); $returnValue = ExcelError::NAN(); $aArgs = self::filterArguments($aArgs); $valueCount = count($aArgs); if ($valueCount > 0) { sort($aArgs, SORT_NUMERIC); $valueCount = $valueCount / 2; if ($valueCount == floor($valueCount)) { $returnValue = ($aArgs[$valueCount--] + $aArgs[$valueCount]) / 2; } else { $valueCount = floor($valueCount); $returnValue = $aArgs[$valueCount]; } } return $returnValue; } /** * MODE. * * Returns the most frequently occurring, or repetitive, value in an array or range of data * * Excel Function: * MODE(value1[,value2[, ...]]) * * @param mixed ...$args Data values * * @return float|string The result, or a string containing an error */ public static function mode(...$args) { $returnValue = ExcelError::NA(); // Loop through arguments $aArgs = Functions::flattenArray($args); $aArgs = self::filterArguments($aArgs); if (!empty($aArgs)) { return self::modeCalc($aArgs); } return $returnValue; } protected static function filterArguments(array $args): array { return array_filter( $args, function ($value) { // Is it a numeric value? return is_numeric($value) && (!is_string($value)); } ); } /** * Special variant of array_count_values that isn't limited to strings and integers, * but can work with floating point numbers as values. * * @return float|string */ private static function modeCalc(array $data) { $frequencyArray = []; $index = 0; $maxfreq = 0; $maxfreqkey = ''; $maxfreqdatum = ''; foreach ($data as $datum) { $found = false; ++$index; foreach ($frequencyArray as $key => $value) { if ((string) $value['value'] == (string) $datum) { ++$frequencyArray[$key]['frequency']; $freq = $frequencyArray[$key]['frequency']; if ($freq > $maxfreq) { $maxfreq = $freq; $maxfreqkey = $key; $maxfreqdatum = $datum; } elseif ($freq == $maxfreq) { if ($frequencyArray[$key]['index'] < $frequencyArray[$maxfreqkey]['index']) { $maxfreqkey = $key; $maxfreqdatum = $datum; } } $found = true; break; } } if ($found === false) { $frequencyArray[] = [ 'value' => $datum, 'frequency' => 1, 'index' => $index, ]; } } if ($maxfreq <= 1) { return ExcelError::NA(); } return $maxfreqdatum; } }