Andrew Sackville-West andrew at swclan.homelinux.org
Fri Oct 17 19:52:28 EDT 2008

```On Thu, Oct 16, 2008 at 09:57:39AM +0100, Paul Johnston wrote:
> Bit of basic maths.
> You are using a power series to approximate sine
> This works by taking an expansion about a fixed point, usually zero.
> It only works well around that point.
> If you get far away it works badly.
> You need to exploit the cyclic nature of the trignometrical functions i.e.
> Sin x = sin ((2 * pi) + x) = sin ((4 * pi) + x)
> Essentially consider the shift in multiples of 2 * pi and calculate the value of x nearest to zero.
>
> See
> http://en.wikipedia.org/wiki/Taylor_series
> The diagram on the top right is very instructive.

how appropriate. We're doing this in math right now ;)

ISTM that OP should take x modulo pi and (per the wiki diagram) a
seven term series to get a nice usable sine function. (and don't
forget to watch for the sign (nopun) of the result)

fact 1 = 1
fact x = x * (fact \$ x - 1)

term n x = (-1)**n * (theta**(2*n + 1) / fact(2*n + 1))
where theta = pi * ((x / pi) - xTrunc) * sign
xTrunc = fromIntegral \$ truncate (x/pi)
sign = (-1)**xTrunc

sine x = sum \$ take 7 [term n x | n<-[0..]]

Wow, that took me a lot longer to figure out because of all the mixing
of numeric types. The critical part was fromIntegral in the poorly
name xTrunc function.

but it looks pretty accurate.

*Main> maximum [sine x - sin x | x<-[1..100]]
1.2652798913048713e-5

and it's easy to boost the accuracy by taking more terms in the
series.

taking 9:

*Main> maximum [sine x - sin x | x<-[1..100]]
1.1683279538265978e-8

taking 11:
*Main> maximum [sine x - sin x | x<-[1..100]]
4.694897248747054e-12

I'm sure there must be a better way to get x modulo pi, but I don't
know enough...

I'd love some feedback on my solution both from a math and a haskell perspective.

A

>
> Paul
>
> -----Original Message-----
> From: beginners-bounces at haskell.org [mailto:beginners-bounces at haskell.org] On Behalf Of Jeffrey Drake
> Sent: Thursday, October 16, 2008 9:47 AM
>
>
> I have defined myself a set of functions to test:
>
> fact 1 = 1
> fact n = n * (fact \$ n - 1)
>
> sine x = x - (x^3/(fact 3)) + (x^5/(fact 5)) - (x^7/(fact 7))
>
> Where my code is 'sine' and the prelude's is sin:
> *Main> sine 1
> 0.841468253968254
> *Main> sin 1
> 0.8414709848078965
>
> *Main> sine 2
> 0.9079365079365079
> *Main> sin 2
> 0.9092974268256817
>
> *Main> sine 3
> 9.107142857142847e-2
> *Main> sin 3
> 0.1411200080598672
>
> *Main> sine 4
> -1.3841269841269837
> *Main> sin 4
> -0.7568024953079282
>
> After 2 they seem to diverge rather rapidly, and I am not sure why. Any ideas?
>
> I would have thought that 4 terms would have been enough.
>
> - Jeff.
>
> _______________________________________________
> Beginners mailing list
> _______________________________________________
> Beginners mailing list
>

--
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 197 bytes
Desc: Digital signature