Numeric error propagation: Difference between revisions
Content added Content deleted
Thundergnat (talk | contribs) m (syntax highlighting fixup automation) |
SqrtNegInf (talk | contribs) (→{{header|Perl}}: eliminated 'uninitialized' warnings, added subroutine signatures, additional tweaks) |
||
Line 1,692:
=={{header|Perl}}==
Following code keeps track of covariance between variables. Each variable with error contains its mean value and components of error source from a set of
<syntaxhighlight lang="perl">use
package ErrVar;
# helper function, apply function 'f' to pairs (a, b) from listX and listY
my @out;
$y = [(0) x @$x] unless @$y; # if not defined
\@out
}
use overload
'sqrt' => \&_sqrt,
;
# make a variable with mean value and a list of coefficient to
# variables providing independent errors
sub make ($x, @v) { bless [$x, @v] }
# mean value of the var, or just the input if it's not of this class
sub mean ($x) { ref $x && $x->isa(__PACKAGE__) ? $x->[0] : $x }
# return variance index array
sub vlist ($x) { ref $x && $x->isa(__PACKAGE__) ? $x->[1] : [] }
sub variance ($x) {
return 0 unless ref($x) and $x->isa(__PACKAGE__);
my $s;
$s += $_ * $_ for @{$x->[1]};
$s
}
sub covariance ($x, $y) {
return 0 unless ref($x) && $x->isa(__PACKAGE__);
my $s;
zip sub ($a,$b) { $s += $a * $b }, vlist($x), vlist($y);
}
sub sigma ($v) { sqrt variance
# to determine if a var is probably zero. we use 1σ here
sub _bool ($x, $, $) {
abs(mean $x) > sigma $x
}
sub _ncmp ($a, $b, $) {
}
sub _neg ($x, $, $) {
bless [ -mean($x), [map(-$_, @{vlist $x}) ] ];
}
sub _add ($x, $y, $) {
bless [$x0 + $y0, zip sub ($a,$b) {$a + $b}, $xv, $yv]
}
sub _sub ($x, $y, $) {
}
sub _mul ($x, $y, $) {
$yv = [ map($x0 * $_, @$yv) ];
}
sub _div ($x, $y, $) {
$xv = [ map($_/$y0, @$xv) ];
bless [$x0 / $y0, zip sub ($a,$b) {$a + $b}, $xv, $yv]
}
sub _sqrt ($x, $, $) {
my ($x0, $xv) = ( mean($x), vlist($x) );
bless [$x0, $xv]
}
sub _pow ($x, $y, $) {
die "Can't take pow of negative number $x" if int($y) != $y or $y & 1;
}
exp($y * log $x)
}
sub _exp ($x, $, $) {
my ($x0, $xv) = ( exp(mean($x)), vlist($x) );
bless [ $x0, [map($x0 * $_, @$xv) ] ]
}
sub _log ($x, $, $) {
my ($x0, $xv) = ( mean($x), vlist($x) );
bless [ log($x0), [ map($_ / $x0, @$xv) ] ]
}
sub _str { sprintf '%g±%.3g', $_[0][0], sigma($_[0]) }
package main;
Line 1,873 ⟶ 1,828:
my $z1 = sqrt(($x1 - $x2) ** 2 + ($y1 - $y2) ** 2);
# this is not for task requirement
my $a = $x1 + $x2;
my $b = $y1 - 2 * $x2;
{{out}}
<pre>distance: 111.803±2.49
covariance between 300±2.46 and -350±4.56: -9.68</pre>
=={{header|Phix}}==
|