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!
Leave a comment