March 2014 update

This commit is contained in:
Ingy döt Net 2014-04-02 16:56:35 +00:00
parent 09687c4926
commit a25938f123
1846 changed files with 21876 additions and 5203 deletions

View file

@ -1,44 +1,61 @@
my @coeff = reverse <DATA>;
use strict;
use warnings;
use constant pi => 4*atan2(1, 1);
use constant e => exp(1);
sub Gamma {
my $x = shift;
my $s;
$s = $s*($x-1) + $_ for @coeff;
return 1 / $s;
my $z = shift;
my $method = shift // 'lanczos';
if ($method eq 'lanczos') {
use constant g => 9;
$z < .5 ? pi / sin(pi * $z) / Gamma(1 - $z, $method) :
sqrt(2* pi) *
($z + g - .5)**($z - .5) *
exp(-($z + g - .5)) *
do {
my @coeff = qw{
1.000000000000000174663
5716.400188274341379136
-14815.30426768413909044
14291.49277657478554025
-6348.160217641458813289
1301.608286058321874105
-108.1767053514369634679
2.605696505611755827729
-0.7423452510201416151527e-2
0.5384136432509564062961e-7
-0.4023533141268236372067e-8
};
my ($sum, $i) = (shift(@coeff), 0);
$sum += $_ / ($z + $i++) for @coeff;
$sum;
}
} elsif ($method eq 'taylor') {
$z < .5 ? Gamma($z+1, $method)/$z :
$z > 1.5 ? ($z-1)*Gamma($z-1, $method) :
do {
my $s = 0; ($s *= $z-1) += $_ for qw{
0.00000000000000000002 -0.00000000000000000023 0.00000000000000000141
0.00000000000000000119 -0.00000000000000011813 0.00000000000000122678
-0.00000000000000534812 -0.00000000000002058326 0.00000000000051003703
-0.00000000000369680562 0.00000000000778226344 0.00000000010434267117
-0.00000000118127457049 0.00000000500200764447 0.00000000611609510448
-0.00000020563384169776 0.00000113302723198170 -0.00000125049348214267
-0.00002013485478078824 0.00012805028238811619 -0.00021524167411495097
-0.00116516759185906511 0.00721894324666309954 -0.00962197152787697356
-0.04219773455554433675 0.16653861138229148950 -0.04200263503409523553
-0.65587807152025388108 0.57721566490153286061 1.00000000000000000000
}; 1/$s;
}
} elsif ($method eq 'stirling') {
no warnings qw(recursion);
$z < 100 ? Gamma($z + 1, $method)/$z :
sqrt(2*pi*$z)*($z/e + 1/(12*e*$z))**$z / $z;
} else { die "unknown method '$method'" }
}
for (1 .. 10) {
$_ /= 3;
printf "Gamma(%.5f) ≈ %.14e\n", $_, Gamma($_);
for my $method (qw(lanczos taylor stirling)) {
printf "%10s: ", $method;
print join(' ', map { sprintf "%.12f", Gamma($_/3, $method) } 1 .. 10);
print "\n";
}
__DATA__
1.00000000000000000000
0.57721566490153286061
-0.65587807152025388108
-0.04200263503409523553
0.16653861138229148950
-0.04219773455554433675
-0.00962197152787697356
0.00721894324666309954
-0.00116516759185906511
-0.00021524167411495097
0.00012805028238811619
-0.00002013485478078824
-0.00000125049348214267
0.00000113302723198170
-0.00000020563384169776
0.00000000611609510448
0.00000000500200764447
-0.00000000118127457049
0.00000000010434267117
0.00000000000778226344
-0.00000000000369680562
0.00000000000051003703
-0.00000000000002058326
-0.00000000000000534812
0.00000000000000122678
-0.00000000000000011813
0.00000000000000000119
0.00000000000000000141
-0.00000000000000000023
0.00000000000000000002