diff --git a/src/Numerics/Statistics/Percentile.cs b/src/Numerics/Statistics/Percentile.cs index 00b8e808..019e85e4 100644 --- a/src/Numerics/Statistics/Percentile.cs +++ b/src/Numerics/Statistics/Percentile.cs @@ -90,11 +90,6 @@ namespace MathNet.Numerics.Statistics throw new ArgumentNullException("data"); } - if (data.Count() < 3) - { - throw new ArgumentException(string.Format(Properties.Resources.MustContainAtLeast, 3), "data"); - } - _data = new List(data); _data.Sort(); } @@ -106,12 +101,12 @@ namespace MathNet.Numerics.Statistics /// the requested percentile. public double Compute(double percentile) { - if (percentile < 0 || percentile > 100) + if (percentile < 0 || percentile > 1 || _data.Count == 0) { - throw new ArgumentException("Percentile value must be between 0 and 100."); + return double.NaN; } - if (percentile == 0.0) + if (percentile == 0.0 || _data.Count == 1) { return _data[0]; } @@ -190,6 +185,9 @@ namespace MathNet.Numerics.Statistics { var k = (int)(_data.Count * percentile); var pk = (k - 0.5) / _data.Count; + if(k == 0) + return _data[0]; + return _data[k - 1] + (_data.Count * (percentile - pk) * (_data[k] - _data[k - 1])); } @@ -202,6 +200,11 @@ namespace MathNet.Numerics.Statistics { var tmp = percentile * (_data.Count + 1.0); var k = (int)tmp; + if(k == 0) + return _data[0]; + if(k == _data.Count) + return _data[k - 1]; + var d = tmp - k; return _data[k - 1] + (d * (_data[k] - _data[k - 1])); diff --git a/src/UnitTests/StatisticsTests/PercentileTests.cs b/src/UnitTests/StatisticsTests/PercentileTests.cs index 0cad934f..940ffcf0 100644 --- a/src/UnitTests/StatisticsTests/PercentileTests.cs +++ b/src/UnitTests/StatisticsTests/PercentileTests.cs @@ -99,32 +99,25 @@ namespace MathNet.Numerics.UnitTests.StatisticsTests } /// - /// Small dataset throws ArgumentException. + /// Empty dataset returns NaN. /// [Test] - public void SmallDataSetThrowArgumentException() + public void EmptyDataSetReturnsNaN() { var data = new double[] { }; - var data1 = data; - Assert.Throws(() => new Percentile(data1)); - - data = new double[] { 1 }; - var data2 = data; - Assert.Throws(() => new Percentile(data2)); - - data = new double[] { 1, 2 }; - Assert.Throws(() => new Percentile(data)); + var percentile = new Percentile(data); + Assert.IsTrue(double.IsNaN(percentile.Compute(0))); } /// - /// Invalid percentile values throw ArgumentException. + /// Invalid percentile values return NaN. /// [Test] - public void InvalidPercentileValuesThrowArgumentException() + public void InvalidPercentileValuesReturnNaN() { var percentile = new Percentile(Data); - Assert.Throws(() => percentile.Compute(-0.1)); - Assert.Throws(() => percentile.Compute(100.1)); + Assert.IsTrue(double.IsNaN(percentile.Compute(-0.1))); + Assert.IsTrue(double.IsNaN(percentile.Compute(1.1))); } } }