diff --git a/src/Numerics/Statistics/ArrayStatistics.cs b/src/Numerics/Statistics/ArrayStatistics.cs
index 9383347c..b304a5c2 100644
--- a/src/Numerics/Statistics/ArrayStatistics.cs
+++ b/src/Numerics/Statistics/ArrayStatistics.cs
@@ -80,7 +80,7 @@ namespace MathNet.Numerics.Statistics
}
///
- /// Returns the sample mean from the unsorted data array.
+ /// Returns the arithmetic sample mean from the unsorted data array.
/// Returns NaN if data is empty or any entry is NaN.
///
/// Sample array, no sorting is assumed.
diff --git a/src/Numerics/Statistics/StreamingStatistics.cs b/src/Numerics/Statistics/StreamingStatistics.cs
index 057c7e12..24bf525f 100644
--- a/src/Numerics/Statistics/StreamingStatistics.cs
+++ b/src/Numerics/Statistics/StreamingStatistics.cs
@@ -46,7 +46,7 @@ namespace MathNet.Numerics.Statistics
var min = double.PositiveInfinity;
bool any = false;
- foreach (double d in stream)
+ foreach (var d in stream)
{
if (d < min || double.IsNaN(d))
{
@@ -68,7 +68,7 @@ namespace MathNet.Numerics.Statistics
var max = double.NegativeInfinity;
bool any = false;
- foreach (double d in stream)
+ foreach (var d in stream)
{
if (d > max || double.IsNaN(d))
{
@@ -78,5 +78,23 @@ namespace MathNet.Numerics.Statistics
}
return any ? max : double.NaN;
}
+
+ ///
+ /// Returns the arithmetic sample mean from the enumerable, in a single pass without memoization.
+ /// Returns NaN if data is empty or any entry is NaN.
+ ///
+ /// Sample stream, no sorting is assumed.
+ public static double Mean(IEnumerable stream)
+ {
+ if (stream == null) throw new ArgumentNullException("stream");
+
+ double mean = 0;
+ ulong m = 0;
+ foreach (var d in stream)
+ {
+ mean += (d - mean) / ++m;
+ }
+ return mean;
+ }
}
}
diff --git a/src/UnitTests/StatisticsTests/StatisticsTests.cs b/src/UnitTests/StatisticsTests/StatisticsTests.cs
index eafd6cf2..04772cec 100644
--- a/src/UnitTests/StatisticsTests/StatisticsTests.cs
+++ b/src/UnitTests/StatisticsTests/StatisticsTests.cs
@@ -86,6 +86,7 @@ namespace MathNet.Numerics.UnitTests.StatisticsTests
Assert.Throws(() => StreamingStatistics.Minimum(data));
Assert.Throws(() => StreamingStatistics.Maximum(data));
+ Assert.Throws(() => StreamingStatistics.Mean(data));
}
[Test]
@@ -119,6 +120,7 @@ namespace MathNet.Numerics.UnitTests.StatisticsTests
Assert.DoesNotThrow(() => StreamingStatistics.Minimum(data));
Assert.DoesNotThrow(() => StreamingStatistics.Maximum(data));
+ Assert.DoesNotThrow(() => StreamingStatistics.Mean(data));
}
[TestCase("lottery")]
@@ -134,6 +136,7 @@ namespace MathNet.Numerics.UnitTests.StatisticsTests
var data = _data[dataSet];
AssertHelpers.AlmostEqual(data.Mean, Statistics.Mean(data.Data), 15);
AssertHelpers.AlmostEqual(data.Mean, ArrayStatistics.Mean(data.Data), 15);
+ AssertHelpers.AlmostEqual(data.Mean, StreamingStatistics.Mean(data.Data), 15);
}
[TestCase("lottery")]
@@ -228,11 +231,19 @@ namespace MathNet.Numerics.UnitTests.StatisticsTests
AssertHelpers.AlmostEqual(2d, Statistics.StandardDeviation(gaussian.Samples().Take(10000)), 2);
AssertHelpers.AlmostEqual(1e+9, ArrayStatistics.Mean(gaussian.Samples().Take(10000).ToArray()), 11);
+
+ AssertHelpers.AlmostEqual(1e+9, StreamingStatistics.Mean(gaussian.Samples().Take(10000)), 11);
}
[Test]
public void MinimumOfEmptyMustBeNaN()
{
+ Assert.That(Statistics.Minimum(new double[0]), Is.NaN);
+ Assert.That(Statistics.Minimum(new[] { 2d }), Is.Not.NaN);
+ Assert.That(ArrayStatistics.Minimum(new double[0]), Is.NaN);
+ Assert.That(ArrayStatistics.Minimum(new[] { 2d }), Is.Not.NaN);
+ Assert.That(SortedArrayStatistics.Minimum(new double[0]), Is.NaN);
+ Assert.That(SortedArrayStatistics.Minimum(new[] { 2d }), Is.Not.NaN);
Assert.That(StreamingStatistics.Minimum(new double[0]), Is.NaN);
Assert.That(StreamingStatistics.Minimum(new[] {2d }), Is.Not.NaN);
}
@@ -240,6 +251,12 @@ namespace MathNet.Numerics.UnitTests.StatisticsTests
[Test]
public void MaximumOfEmptyMustBeNaN()
{
+ Assert.That(Statistics.Maximum(new double[0]), Is.NaN);
+ Assert.That(Statistics.Maximum(new[] { 2d }), Is.Not.NaN);
+ Assert.That(ArrayStatistics.Maximum(new double[0]), Is.NaN);
+ Assert.That(ArrayStatistics.Maximum(new[] { 2d }), Is.Not.NaN);
+ Assert.That(SortedArrayStatistics.Maximum(new double[0]), Is.NaN);
+ Assert.That(SortedArrayStatistics.Maximum(new[] { 2d }), Is.Not.NaN);
Assert.That(StreamingStatistics.Maximum(new double[0]), Is.NaN);
Assert.That(StreamingStatistics.Maximum(new[] { 2d }), Is.Not.NaN);
}