bernoulli_numbers_from_primes.sf 961 B

12345678910111213141516171819202122232425262728293031323334353637383940414243444546
  1. #!/usr/bin/ruby
  2. # Daniel "Trizen" Șuteu
  3. # License: GPLv3
  4. # Date: 14 October 2017
  5. # https://github.com/trizen
  6. # A fast algorithm for computing the n-th Bernoulli number, using prime numbers.
  7. # Reference:
  8. # "Computing Bernoulli Numbers Quickly", by Kevin J. McGown (December 8, 2005)
  9. func bern_from_primes(n) {
  10. n == 0 && return 1
  11. n == 1 && return 1/2
  12. n < 0 && return NaN
  13. n & 1 && return 0
  14. var log2B = (log(4*Num.tau*n)/2 + n*log(n) - n*log(Num.tau) - n)/log(2)
  15. local Number!PREC = numify(int(n + log2B) + (n <= 90 ? 18 : 0))
  16. var K = (n! * 2 / Num.tau**n)
  17. var d = 1
  18. for k in (divisors(n)) {
  19. if (is_prime(k + 1)) {
  20. d *= k+1
  21. }
  22. }
  23. var N = ceil((K * d).root(n - 1))
  24. var z = 1
  25. for p in (primes(N)) {
  26. z *= (1 - float(p)**(-n))
  27. }
  28. (-1)**(n/2 + 1) * int(ceil(d * K / z)) / d
  29. }
  30. for n in (0..50) {
  31. printf("B%-3d = %s\n", 2*n, bern_from_primes(2*n).as_rat)
  32. }