summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStaubfinger <staubfingercodinggames@gmail.com>2023-01-08 14:44:59 +0100
committerJelle Raaijmakers <jelle@gmta.nl>2023-02-03 19:04:15 +0100
commit6b9344e86c8cf053cbef58aa57f04e738543a63d (patch)
tree14f09b769be27b73d6bcb824c240d40b69739072
parentbecd6d106f71f112067ba9f989f9c807a8c9dcd2 (diff)
downloadserenity-6b9344e86c8cf053cbef58aa57f04e738543a63d.zip
AK: Use `AK:quickselect_inline` to compute `AK::Statistics::median`
Quick select is an algorithm that is able to find the median of a Vector without fully sorting it. This replaces the old very naive implementation for `AK::Statistics::median()` with `AK::quickselect_inline`
-rw-r--r--AK/Statistics.h33
1 files changed, 27 insertions, 6 deletions
diff --git a/AK/Statistics.h b/AK/Statistics.h
index 9caf69ad77..93df7bd110 100644
--- a/AK/Statistics.h
+++ b/AK/Statistics.h
@@ -8,7 +8,7 @@
#include <AK/Concepts.h>
#include <AK/Math.h>
-#include <AK/QuickSort.h>
+#include <AK/QuickSelect.h>
#include <AK/Vector.h>
namespace AK {
@@ -27,10 +27,24 @@ public:
}
T const sum() const { return m_sum; }
- float average() const { return (float)sum() / size(); }
+
+ // FIXME: Unclear Wording, average can mean a lot of different things
+ // Median, Arithmetic Mean (which this is), Geometric Mean, Harmonic Mean etc
+ float average() const
+ {
+ // Let's assume the average of an empty dataset is 0
+ if (size() == 0)
+ return 0;
+
+ // TODO: sum might overflow so maybe do multiple partial sums and intermediate divisions here
+ return (float)sum() / size();
+ }
T const min() const
{
+ // Lets Rather fail than read over the end of a collection
+ VERIFY(size() != 0);
+
T minimum = m_values[0];
for (T number : values()) {
if (number < minimum) {
@@ -42,6 +56,9 @@ public:
T const max() const
{
+ // Lets Rather fail than read over the end of a collection
+ VERIFY(size() != 0);
+
T maximum = m_values[0];
for (T number : values()) {
if (number > maximum) {
@@ -51,16 +68,20 @@ public:
return maximum;
}
- // FIXME: Implement a better algorithm
T const median()
{
- quick_sort(m_values);
+ // Let's assume the Median of an empty dataset is 0
+ if (size() == 0)
+ return 0;
+
// If the number of values is even, the median is the arithmetic mean of the two middle values
if (size() % 2 == 0) {
auto index = size() / 2;
- return (m_values.at(index) + m_values.at(index + 1)) / 2;
+ auto median1 = m_values.at(AK::quickselect_inplace(m_values, index));
+ auto median2 = m_values.at(AK::quickselect_inplace(m_values, index - 1));
+ return (median1 + median2) / 2;
}
- return m_values.at(size() / 2);
+ return m_values.at(AK::quickselect_inplace(m_values, size() / 2));
}
float standard_deviation() const { return sqrt(variance()); }