/// <inheritdoc/> public override double RawMoment(int r) { if (r < 0) { throw new ArgumentOutOfRangeException(nameof(r)); } else { double[] central = CentralMoments(r); return(MomentMath.CentralToRaw(a, central, r)); } }
/// <inheritdoc/> public override double CentralMoment(int r) { if (r < 0) { throw new ArgumentOutOfRangeException(nameof(r)); } else if (r == 0) { return(1.0); } else { double[] K = Cumulants(r); return(MomentMath.CumulantToCentral(K, r)); } }
/// <inheritdoc /> public override double RawMoment(int r) { if (r < 0) { throw new ArgumentOutOfRangeException(nameof(r)); } else if (r == 0) { return(1.0); } else if (r == 1) { return(Mean); } else { double[] C = CentralMoments(r); return(MomentMath.CentralToRaw(Mean, C, r)); } }
/// <inheritdoc /> public override double CentralMoment(int r) { if (r < 0) { throw new ArgumentOutOfRangeException(nameof(r)); } else if (r == 0) { return(1.0); } else if (r == 1) { return(0.0); } else if (r == 2) { return(Variance); } else { double[] K = Cumulants(r); return(MomentMath.CumulantToCentral(K, r)); // Begin with M_r = e^{r \mu + \frac{1}{2} r^2 \sigma^2} and use // C_r = <(x-M_1)^r> = \sum_{k=0}^{r} {r \choose k} M_k (-M_1)^{r-k} // = \sum_{k=0}^{r} (-1)^{r-k} {r \choose k} e^{k \mu + \frac{1}{2} k^2 \sigma^2} e^{(r-k)(\mu + \frac{1}{2} \sigma^2)} // = e^{r (\mu + \frac{1}{2} \sigma^2)} \sum_{k=0}^{r} (-1)^{r-k} {r \choose k} e^{\frac{1}{2} k (k - 1) \sigma^2} // So far, this is just the usual raw to central moment conversion, subject to the usual significant cancellation errors, // particularly for small \sigma, in which case all exponentials will be nearly equal. Write // e^{\frac{1}{2} k (k - 1) \sigma^2} = (e^{\frac{1}{2} k (k - 1) \sigma^2} - 1) + 1. // When summed over all k, the contribution of the final +1 vanishes, so // C_r = e^{r (\mu + \frac{1}{2} \sigma^2)} \sum_{k=0}^{r} (-1)^{r-k} {r \choose k} (e^{\frac{1}{2} k (k - 1) \sigma^2} - 1) // and since ( ) is zero for k = 0 and k = 2, we need not start the sum until k = 2. /* * double s = 0.0; * double x = sigma * sigma / 2.0; * for (int k = 2; k <= r; k++) { * double ds = AdvancedIntegerMath.BinomialCoefficient(r, k) * MoreMath.ExpMinusOne(k * (k - 1) * x); * if ((r - k) % 2 != 0) ds = -ds; * s += ds; * } * return (Math.Exp(r * (mu + x)) * s); */ /* * // This follows from a straightforward expansion of (x-m)^n and substitution of expressions for M_k. * // It eliminates some arithmetic but is still subject to loss of significance due to cancelation. * double s2 = sigma * sigma / 2.0; * * double C = 0.0; * for (int i = 0; i <= r; i++) { * double dC = AdvancedIntegerMath.BinomialCoefficient(r, i) * Math.Exp((MoreMath.Sqr(r - i) + i) * s2); * if (i % 2 != 0) dC = -dC; * C += dC; * } * return (Math.Exp(r * mu) * C); */ // this isn't great, but it does the job // expand in terms of moments about the origin // there is likely to be some cancelation, but the distribution is wide enough that it may not matter /* * double m = -Mean; * double C = 0.0; * for (int k = 0; k <= n; k++) { * C += AdvancedIntegerMath.BinomialCoefficient(n, k) * Moment(k) * Math.Pow(m, n - k); * } * return (C); */ } }
/// <summary> /// Computes a central moment of the distribution. /// </summary> /// <param name="r">The order of the moment to compute.</param> /// <returns>The rth central moment of the distribution.</returns> /// <seealso cref="RawMoment" /> public virtual double CentralMoment(int r) { // This is a terrible way to compute central moments, subject to significant cancelations, so replace it if at all possible. double[] M = RawMoments(r); return(MomentMath.RawToCentral(M, r)); }
/// <summary> /// Computes a cumulant of the distribution. /// </summary> /// <param name="r">The index of the cumulant to compute.</param> /// <returns>The rth cumulant of the distribution.</returns> /// <seealso href="http://en.wikipedia.org/wiki/Cumulant"/> public virtual double Cumulant(int r) { double[] C = CentralMoments(r); double[] K = MomentMath.CentralToCumulant(Mean, C); return(K[r]); }