Skip to content

feat(maths): implement discrete and continuous series for Mean and Median algorithms - #197

Open
mrfiiqane wants to merge 2 commits into
TheAlgorithms:masterfrom
mrfiiqane:master
Open

mrfiiqane wants to merge 2 commits into
TheAlgorithms:masterfrom
mrfiiqane:master

Conversation

@mrfiiqane

Copy link
Copy Markdown

This Pull Request expands the statistical algorithms in the repository by adding support for Discrete and Continuous series to both the Mean and Median calculations. Previously, only the Individual series were supported.

Changes included:

Added mean_discrete and mean_continuous functions to Mean.php
Added median_discrete and median_continuous functions to Median.php
Added mathematical formulas
Implemented unit tests
All code has been formatted according to PSR-12 and strict typing has been used throughout.

…dian

- Added mean_discrete and mean_continuous functions in Maths/Mean.php

- Added median_discrete and median_continuous functions in Maths/Median.php

- Included explicit inline documentation and mathematical formula comments for all new functions

- Implemented comprehensive PHPUnit test cases in tests/Maths/MathsTest.php to validate expected output and edge cases

@darwinz darwinz left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the contribution, the formulas and docblocks are clear!

I merged this against current master locally. The tests pass, but vendor/bin/phpcs -n reports 7 errors (CI will fail), and median_discrete returns the wrong result when a value has frequency 0. The details are in the inline comments; the main items are the lint errors, the zero-frequency bug, input validation, and a few more tests.

You can check locally with composer test and vendor/bin/phpcs -n. Thanks!

return $item['value'];
}
if ($cumulativeFrequency == $targetCF) {
$prevValue = $item['value'];

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: a value with frequency 0 that comes right after the cumulative frequency lands exactly on N/2 overwrites $prevValue, because the cumulative frequency is still equal to the target.

median_discrete([10, 15, 20], [2, 0, 2]) returns 17.5, but the data is 10, 10, 20, 20, so the median is 15. Please guard this with $item['freq'] > 0 and add this case to testMedianDiscrete.

Comment thread Maths/Median.php Outdated
$f = $item['f'];
$h = $item['U'] - $item['L'];

if ($f == 0) continue;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This continue can never run: if a class reaches the target with f == 0, the previous class already reached it and returned. Please remove it. As a one-line if without braces, it's also a PSR-12 error (Inline control structures are not allowed).

Comment thread Maths/Median.php Outdated
$prevCF = $cumulativeFrequency;
}

return 0;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This line is unreachable once the total frequency is positive. If it ever were reached, returning 0 would look like a valid median. I'd throw an exception here instead.

Comment thread Maths/Median.php Outdated
sort($numbers);
$length = count($numbers);

// Using intdiv to find the middle index corresponds to the mathematical formula m = (n+1)/2.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This comment is unrelated to the PR, and it's a bit misleading: intdiv($length, 2) isn't really the formula m = (n+1)/2. Could you drop this change to median()? Lines 28 and 33 also have trailing whitespace.

* @return int|float Median of the discrete series
* @throws \Exception
*/
function median_discrete(array $values, array $frequencies): int|float

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

median() above validates its input with is_numeric and throws a clear \Exception. The new functions don't validate: non-numeric values give a raw TypeError, and negative frequencies are accepted. Please add the same kind of validation for values, bounds and frequencies (frequencies should be >= 0). This applies to all four new functions.

}

$sumProduct = 0;
for ($i = 0; $i < count($values); $i++) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indexing with $values[$i] assumes list keys. mean_discrete(['a' => 10, 'b' => 20], [1, 1]) gives "Undefined array key" warnings and returns 0. Calling array_values() on the inputs at the start of each function fixes this (same for the other three functions).

Comment thread Maths/Mean.php Outdated

/**
* Calculates the mean of a discrete series.
*

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Trailing whitespace here and on line 47. vendor/bin/phpcs -n reports 7 errors across Mean.php and Median.php, and CI will fail on them. vendor/bin/phpcbf fixes them all automatically.

Comment thread tests/Maths/MathsTest.php
median('a', 'b', 'c');
}

public function testMedianDiscrete()

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you add exception tests for median_discrete and median_continuous (mismatched lengths, empty input, zero total frequency), plus a zero-total-frequency test for the mean functions? A case with unsorted input would also be good, since both median functions sort.

@darwinz darwinz left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Marking this as changes requested so it isn't merged before the items in my review above are addressed. Please see the inline comments there.

@mrfiiqane

Copy link
Copy Markdown
Author

Hi @darwinz, thank you for the detailed review

Bug fixes:

Fixed zero-frequency bug in median_discrete by adding $item['freq'] > 0 guard
Removed unreachable if ($f == 0) continue in median_continuous
Replaced return 0 fallback with throw new \Exception(...) in both median functions
Code quality:

Added array_values() to all four new functions to handle non-list keys
Added full input validation (numeric values, non-negative frequencies) to all new functions
Removed the misleading comment from median()
Fixed all 7 trailing-whitespace lint errors (vendor/bin/phpcbf)
Tests added:

Exception tests: mismatched arrays, empty input, zero total frequency — for all new functions
Zero-frequency edge case for median_discrete
Unsorted input cases for all functions
Added mode_discrete and mode_continuous to Mode.php (matching the pattern of Mean and Median)
Restructured files into Maths/MeasuresOfCentralTendency/ subfolder with real-world notebook examples included as reference images.

All tests pass (composer run-script test) and vendor/bin/phpcs -n reports 0 errors

                                                        Thanks

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants