在 Raku 中求解指数方程
solving an exponential equation in Raku
我正在尝试这样求解这个指数方程:
my ($l,$r);
for (1 .. 100) -> $x {
$l = $x * e ** $x;
$r = 5 * (e ** $x - 1);
say $x if $l == $r;
}
但是没用。如何简单全面的解决?
对于 Perl 5,有 Math::GSL::Roots - 求任意一维函数的根
https://metacpan.org/pod/Math::GSL::Roots
Raku 支持使用 Perl 5 代码或者可以直接访问 GSL C 库,不是吗?
$fspec = sub {
my ( $x ) = shift;
# here the function has to be inserted in the format
# return leftside - rightside;
return ($x + $x**2) - 4;
};
gsl_root_fsolver_alloc($T); # where T is the solver algorithm, see link for the 6 type constants, e.g. $$gsl_root_fsolver_brent
gsl_root_fsolver_set( $s, $fspec, $x_lower, $x_upper ); # [$x_lower; $x_upper] is search interval
gsl_root_fsolver_iterate($s);
gsl_root_fsolver_iterate($s);
gsl_root_fsolver_iterate($s);
gsl_root_fsolver_iterate($s);
gsl_root_fsolver_iterate($s);
my $result = gsl_root_fsolver_root($s);
gsl_root_fsolver_free (s);
如果函数的导数可用,则有可用的增强算法 (gsl_root_fdfsolver_*)。
另请参阅 https://www.gnu.org/software/gsl/doc/html/roots.html#examples 了解一般用法
抱歉重复回答。
但这是在 Raku 中解决的一个完全不同的更简单的方法。
(它可能可以更优雅地表述。)
#!/usr/bin/env raku
sub solver ($equ, $acc, $lower0, $upper0) {
my Real $lower = $lower0;
my Real $upper = $upper0;
my Real $middle = ($lower + $upper) / 2;
# zero must be in between
sign($equ($lower)) != sign($equ($upper)) || die 'Bad interval!';
for ^$acc { # accuracy steps
if sign($equ($lower)) != sign($equ($middle))
{ $upper = $middle }
else
{ $lower = $middle }
$middle = ($upper + $lower) / 2;
}
return $middle;
}
my $equ = -> $x { $x * e ** $x - 5 * (e ** $x - 1) }; # left side - right side
my $acc = 64; # 64 bit accuracy
my Real $lower = 1; # start search here
my Real $upper = 100; # end search here
my $solution = solver $equ, $acc, $lower, $upper;
say 'result is ', $solution;
say 'Inserted in equation calculates to ', $equ($solution), ' (hopefully nearly zero)'
我正在尝试这样求解这个指数方程:
my ($l,$r);
for (1 .. 100) -> $x {
$l = $x * e ** $x;
$r = 5 * (e ** $x - 1);
say $x if $l == $r;
}
但是没用。如何简单全面的解决?
对于 Perl 5,有 Math::GSL::Roots - 求任意一维函数的根
https://metacpan.org/pod/Math::GSL::Roots
Raku 支持使用 Perl 5 代码或者可以直接访问 GSL C 库,不是吗?
$fspec = sub {
my ( $x ) = shift;
# here the function has to be inserted in the format
# return leftside - rightside;
return ($x + $x**2) - 4;
};
gsl_root_fsolver_alloc($T); # where T is the solver algorithm, see link for the 6 type constants, e.g. $$gsl_root_fsolver_brent
gsl_root_fsolver_set( $s, $fspec, $x_lower, $x_upper ); # [$x_lower; $x_upper] is search interval
gsl_root_fsolver_iterate($s);
gsl_root_fsolver_iterate($s);
gsl_root_fsolver_iterate($s);
gsl_root_fsolver_iterate($s);
gsl_root_fsolver_iterate($s);
my $result = gsl_root_fsolver_root($s);
gsl_root_fsolver_free (s);
如果函数的导数可用,则有可用的增强算法 (gsl_root_fdfsolver_*)。
另请参阅 https://www.gnu.org/software/gsl/doc/html/roots.html#examples 了解一般用法
抱歉重复回答。
但这是在 Raku 中解决的一个完全不同的更简单的方法。
(它可能可以更优雅地表述。)
#!/usr/bin/env raku
sub solver ($equ, $acc, $lower0, $upper0) {
my Real $lower = $lower0;
my Real $upper = $upper0;
my Real $middle = ($lower + $upper) / 2;
# zero must be in between
sign($equ($lower)) != sign($equ($upper)) || die 'Bad interval!';
for ^$acc { # accuracy steps
if sign($equ($lower)) != sign($equ($middle))
{ $upper = $middle }
else
{ $lower = $middle }
$middle = ($upper + $lower) / 2;
}
return $middle;
}
my $equ = -> $x { $x * e ** $x - 5 * (e ** $x - 1) }; # left side - right side
my $acc = 64; # 64 bit accuracy
my Real $lower = 1; # start search here
my Real $upper = 100; # end search here
my $solution = solver $equ, $acc, $lower, $upper;
say 'result is ', $solution;
say 'Inserted in equation calculates to ', $equ($solution), ' (hopefully nearly zero)'