## Fun with series

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!

Advertisements