On #perl6 this morning, rokoteko was curious about doing Taylor series in Perl 6. This sort of thing fascinates me, so I quickly coded up this:
sub sine-power($x) {
my $sign = 1;
gather for 1, 3 ... * -> $n {
take $sign * $x ** $n / [*] (1 ... $n);
$sign *= -1;
}
}
That works, and is pretty straightforward. However, it’s got one big glitch in it, IMO. Even if you feed it a Rat input, it will always return a list of Nums, because $x ** $n returns a Num. (Hmmm…. might that be worth changing?)
No problem, you just need to complicate the function a bit by keeping running products for the numerator and denominator:
sub sine-power($x) {
my $sign = 1;
my $x-part = $x;
my $denom = 1;
gather for 3, 5 ... * -> $n {
take $sign * $x-part / $denom;
$sign *= -1;
$x-part *= $x * $x;
$denom *= $n * ($n - 1);
}
}
As a bonus, the new version should be faster.
Let’s see if it works:
> say sine-power(0.1).munch(4).perl; (1/10, -1/6000, 1/12000000, -1.98412698412698e-11) > say ([+] sine-power(0.1).munch(3)).perl; 1198001/12000000 > say [+] sine-power(0.1).munch(3); 0.0998334166666667 say sin(0.1); 0.0998334166468282
As you can see, this generates a Rat approximation for sin(0.1) which is accurate to 10 decimal places. Not bad!