Ejemplo n.º 1
0
        /// <summary>
        /// Computes the given Bernoulli number.
        /// </summary>
        /// <param name="n">The index of the Bernoulli number to compute, which must be non-negative.</param>
        /// <returns>The Bernoulli number B<sub>n</sub>.</returns>
        /// <exception cref="ArgumentOutOfRangeException"><paramref name="n"/> is negative.</exception>
        /// <remarks>
        /// <para>B<sub>n</sub> vanishes for all odd n except n=1. For n about 260 or larger, B<sub>n</sub> overflows a double.</para>
        /// </remarks>
        /// <seealso href="http://en.wikipedia.org/wiki/Bernoulli_number"/>
        /// <seealso href="http://mathworld.wolfram.com/BernoulliNumber.html"/>
        public static double BernoulliNumber(int n)
        {
            if (n < 0)
            {
                throw new ArgumentOutOfRangeException(nameof(n));
            }

            // B_1 is the only odd Bernoulli number.
            if (n == 1)
            {
                return(-1.0 / 2.0);
            }

            // For all other odd arguments, return zero.
            if (n % 2 != 0)
            {
                return(0.0);
            }

            // If the argument is small enough, look up the answer in our stored array.
            int m = n / 2;

            if (m < Bernoulli.Length)
            {
                return(Bernoulli[m]);
            }

            // Otherwise, use the relationship with the Riemann zeta function to get the Bernoulli number.
            // Since this is only done for large n, it would probably be faster to just sum the zeta series explicitly here.
            double B = 2.0 * AdvancedMath.RiemannZeta(n) / AdvancedMath.PowOverGammaPlusOne(Global.TwoPI, n);

            if (m % 2 == 0)
            {
                B = -B;
            }
            return(B);
        }