Welch's t-test: Difference between revisions
→Using Burkhardt's 'incomplete beta': general trimming and clean-up
Thundergnat (talk | contribs) m (→Using Burkardt's betain: fix so it actually compiles) |
SqrtNegInf (talk | contribs) (→Using Burkhardt's 'incomplete beta': general trimming and clean-up) |
||
Line 956:
</pre>
=== Using
We use a slightly more accurate lgamma than the C code. Note that Perl can be compiled with different underlying floating point representations -- double, long double, or quad double.
{{trans|C}}
<lang perl>use strict;
use warnings;
use
sub lgamma {
Line 978:
}
sub calculate_P_value {
my ($array1,$array2) = (shift, shift);
my $mean1 = sum(@$array1);
my $mean2 = sum(@$array2);
$mean1 /= scalar @$array1;
$mean2 /= scalar @$array2;
my ($variance1,$variance2);
return 1 if $variance1 == 0 and $variance2 == 0;
$variance1 = $variance1/(@$array1-1);
$variance2 = $variance2/(@$array2-1);
my $Welch_t_statistic = ($mean1-$mean2)/sqrt($variance1/$array1_size+$variance2/$array2_size);
my $DoF = (($variance1/@$array1+$variance2/@$array2)**2) /
(
($variance1*$variance1)/(@$array1*@$array1*(@$array1-1)) +
($variance2*$variance2)/(@$array2*@$array2*(@$array2-1))
);
my $A = $DoF / 2;
my $value = $DoF / ($Welch_t_statistic**2 + $DoF);
return $value if $A <= 0 or $value <= 0 or 1 <= $value;
# from here, translation of John Burkhardt's C code
my $beta = lgamma($A) + 0.57236494292470009 - lgamma($A+0.5); constant is logΓ(.5), more precise than 'lgamma' routine
my $eps = 10**-15;
my($ai,$cx,$indx,$ns,$pp,$psq,$qq,$qq_ai,$rx,$term,$xx);
$psq = $A + 0.5;
$cx = 1 - $value;
if ($A < $psq * $value) { ($xx, $cx, $pp, $qq, $indx) = ($cx, $value, 0.5, $A, 1) }
else { ($xx, $pp, $qq, $indx) = ($value, $A, 0.5, 0) }
$term = $ai = $value = 1;
$ns = int $qq + $cx * $psq;
# Soper reduction formula
$qq_ai = $qq - $ai;
$rx = $ns == 0 ? $xx : $xx / $cx;
while (1) {
$term = $term * $qq_ai * $rx / ( $pp + $ai );
$value = $value + $term;
$qq_ai = abs($term);
$value = 1 - $value if $indx;
last;
$ns--;
if ($ns >= 0) {
$qq_ai = $qq - $ai;
} else {
$qq_ai = $psq;
$psq = $psq + 1;
}
}
$value
}
Line 1,106 ⟶ 1,082:
while (@tests) {
my ($left, $right) = splice(@tests, 0, 2);
my $pvalue =
$error += abs($pvalue - shift @answers);
printf("p-value = %.14g\n",$pvalue);
|