zeta_2n.pl 934 B

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647
  1. #!/usr/bin/perl
  2. # Calculate zeta(2n) using a closed-form formula.
  3. # See also:
  4. # https://en.wikipedia.org/wiki/Riemann_zeta_function
  5. use 5.010;
  6. use strict;
  7. use warnings;
  8. use lib qw(../lib);
  9. use Memoize qw(memoize);
  10. use experimental qw(signatures);
  11. use Math::AnyNum qw(:overload pi);
  12. sub bernoulli_number($n) { # Akiyama–Tanigawa algorithm
  13. return 1/2 if ($n == 1);
  14. return 0 if ($n % 2 == 1);
  15. my @A;
  16. for my $m (0 .. $n) {
  17. $A[$m] = 1 / ($m + 1);
  18. for (my $j = $m ; $j > 0 ; $j--) {
  19. $A[$j - 1] = $j * ($A[$j - 1] - $A[$j]);
  20. }
  21. }
  22. return $A[0]; # which is Bn
  23. }
  24. sub factorial($n) {
  25. $n < 2 ? 1 : factorial($n - 1) * $n;
  26. }
  27. memoize('factorial');
  28. sub zeta_2n($n) {
  29. (-1)**($n + 1) * (1 << (2 * $n - 1)) * bernoulli_number(2 * $n) / factorial(2 * $n) * pi**(2 * $n);
  30. }
  31. for my $i (1 .. 10) {
  32. say "zeta(", 2 * $i, ") = ", zeta_2n($i);
  33. }