mathnet / mathnet-numerics

Math.NET Numerics
http://numerics.mathdotnet.com
MIT License
3.48k stars 894 forks source link

Chi Squared strange behavior around x=0 #379

Open verybadcat opened 8 years ago

verybadcat commented 8 years ago

I am uncomfortable with the output of the following test. It feels weird that the output is 0 specifically for an input of 0, but not for a negative input. The y2 value should be zero IMO. But certainly it should not be the case that y2=0 and y1 is nonzero.

[Test()]
public void TestMathNetChiSquared() {
  MathNet.Numerics.Distributions.ChiSquared chiSquared = new MathNet.Numerics.Distributions.ChiSquared(2);
  double y1 = chiSquared.Density(-0.01);
  double y2 = chiSquared.Density(0.0);
  double y3 = chiSquared.Density(0.01);
  double y3Error = Math.Abs(y3 - 0.5);
  Assert.Less(y3Error, 0.01); // passes, which is correct behavior from MathNet
  MyCustomLogMethod("y1=", y1, "y2=", y2, "y3=", y3); // prints: y1= 0.502506260429701 y2= 0 y3= 0.497506239596341. 
}
cdrnet commented 8 years ago

Technically negative values are outside of the support range of the Chi-Squared disrtibution, but it would make sense to always return a zero-density outside of the support range. We should check this for all distributions. Then specifically for 2, pdf(0) should return 0.5. We should fix that as well. Thanks for reportig this!

schlebe commented 4 years ago

I have lot of problem to build correction on my PC. So I put here the correct code

        public static double PDF(double freedom, double x)
        {
            if (freedom <= 0.0)
            {
                throw new ArgumentException(Resources.InvalidDistributionParameters);
            }

            if (double.IsPositiveInfinity(freedom) || double.IsPositiveInfinity(x))
            {
                return 0.0;
            }

            if (x == 0.0)
            {
                if (freedom == 2) return 0.5;
                if (freedom == 1) return double.PositiveInfinity;
                return 0.0; 
                }

            if (freedom > 160.0)
            {
                return Math.Exp(PDFLn(freedom, x));
            }

            return (Math.Pow(x, (freedom/2.0) - 1.0)*Math.Exp(-x/2.0))/(Math.Pow(2.0, freedom/2.0)*SpecialFunctions.Gamma(freedom/2.0));
        }

Can somebody implement it on GITHUB ? Thanks

I have just make a specific test when x = 0.

This source code must be implemented in MathNet.Numerics.Distributions.ChiSquared.cs.