// The expansions in which they appear are asymptotic; the numbers grow rapidly after ~B_16 /// <summary> /// Computes a Stirling number of the first kind. /// </summary> /// <param name="n">The upper argument, which must be non-negative.</param> /// <param name="k">The lower argument, which must lie between 0 and n.</param> /// <returns>The value of the unsigned Stirling number of the first kind.</returns> /// <exception cref="ArgumentOutOfRangeException"><paramref name="n"/> is negative, or <paramref name="k"/> /// lies outside [0, n].</exception> /// <seealso href="https://en.wikipedia.org/wiki/Stirling_numbers_of_the_first_kind"/> public static double StirlingNumber1(int n, int k) { if (n < 0) { throw new ArgumentOutOfRangeException(nameof(n)); } if ((k < 0) || (k > n)) { throw new ArgumentOutOfRangeException(nameof(k)); } if (k == n) { return(1.0); } else if (k == 0) { return(0.0); } else if (k == 1) { return(AdvancedIntegerMath.Factorial(n - 1)); } else if (k == (n - 1)) { return(AdvancedIntegerMath.BinomialCoefficient(n, 2)); } else { double[] s = Stirling1_Recursive(n, k); return(s[k]); } }
private static double[] ReimannCoefficients(int n) { double[] e = new double[n]; double sum = 0.0; for (int k = n; k > 0; k--) { sum += (double)AdvancedIntegerMath.BinomialCoefficient(n, k); e[k - 1] = sum; } return(e); }
/// <summary> /// Computes a Stirling number of the second kind. /// </summary> /// <param name="n">The upper argument, which must be non-negative.</param> /// <param name="k">The lower argument, which must lie between 0 and n.</param> /// <returns>The value of the Stirling number of the second kind.</returns> /// <exception cref="ArgumentOutOfRangeException"><paramref name="n"/> is negative, or <paramref name="k"/> /// lies outside [0, n].</exception> /// <seealso href="https://en.wikipedia.org/wiki/Stirling_numbers_of_the_second_kind"/> public static double StirlingNumber2(int n, int k) { if (n < 0) { throw new ArgumentOutOfRangeException(nameof(n)); } if ((k < 0) || (k > n)) { throw new ArgumentOutOfRangeException(nameof(k)); } if ((k == 1) || (k == n)) { return(1.0); } else if (k == 0) { return(0.0); // The exceptional value 1 for n = k = 0 will already have been returned by the previous case. } else if (k == 2) { return(Math.Round(MoreMath.Pow(2.0, n - 1) - 1.0)); } else if (k == (n - 1)) { return(AdvancedIntegerMath.BinomialCoefficient(n, 2)); } else { double[] s = Stirling2_Recursive(n, k); return(s[k]); } // There is a formula for Stirling numbers // { n \brace k } = \frac{1}{k!} \sum{j=0}^{k} (-1)^j { k \choose j} (k - j)^n // which would be faster than recursion, but it has large cancelations between // terms. We could try to use it when all values are less than 2^52, for which // double arithmetic is exact for integers. For k!, that means k < 18. For // largest term in sum for all k, that means n < 14. }