bernoulli_seidel.pl 989 B

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849
  1. #!/usr/bin/perl
  2. # Algorithm from:
  3. # http://oeis.org/wiki/User:Peter_Luschny/ComputationAndAsymptoticsOfBernoulliNumbers#Seidel
  4. use 5.010;
  5. use strict;
  6. use warnings;
  7. use lib qw(../lib);
  8. use Math::AnyNum;
  9. sub bernoulli_seidel {
  10. my ($n) = @_;
  11. state $one = Math::AnyNum->one;
  12. state $zero = Math::AnyNum->zero;
  13. $n == 0 and return $one;
  14. $n == 1 and return $one / 2;
  15. $n % 2 and return $zero;
  16. my @D = ($zero, $one, ($zero) x ($n / 2 - 1));
  17. my ($h, $w) = (1, 1);
  18. foreach my $i (0 .. $n - 1) {
  19. if ($w ^= 1) {
  20. ($D[$_] += $D[$_ - 1]) for (1 .. $h - 1);
  21. }
  22. else {
  23. $w = $h++;
  24. ($D[$w] += $D[$w + 1]) while --$w;
  25. }
  26. }
  27. my $den = ($one << ($n + 1)) - 2;
  28. my $num = $D[$h - 1];
  29. $num = -$num if $n % 4 == 0;
  30. $num / $den;
  31. }
  32. my $from = shift(@ARGV) // 1;
  33. my $to = shift(@ARGV) // 50;
  34. foreach my $n ($from .. $to) {
  35. say "B(", 2 * $n, ") = ", bernoulli_seidel(2 * $n);
  36. }