/// <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); }