マクローリン展開でsin関数

30分プログラム、その725。マクローリン展開でsin関数を作ってみました。
簡単だと思いきや結構大変でした。そもそもラジアンなる単位を半分ぐらい忘れてました。

コードは、itertoolsを使ってやるために、ちょっと工夫をしてます。n番目の項を直接計算するのではなく、階乗のストリームとx^nのストリームをくっつける形で各項の値を計算してます。

使い方

print sin(0)         # => 0
print sin(math.pi/6) # => 0.5
print sin(math.pi/2) # => 1.0

ソースコード

#! /usr/bin/python
# -*- mode:python; coding:utf-8 -*-
#
# sin.py -
#
# Copyright(C) 2010 by mzp
# Author: MIZUNO Hiroki / mzpppp at gmail dot com
# http://howdyworld.org
#
# Timestamp: 2010/01/22 21:53:04
#
# This program is free software; you can redistribute it and/or
# modify it under MIT Lincence.
#
import math
from itertools import *

def take(n, iterable):
    "Return first n items of the iterable as a list"
    return list(islice(iterable, n))

def facts():
    x = 1
    for n in count(1):
        yield x
        x *= n

def skip_even(xs):
    b = False
    for x in xs:
        if b:
            yield x
            b = False
        else:
            b = True

def signs():
    while True:
        yield 1
        yield -1

def x_n(x):
    x_n = 1
    while True:
        yield x_n
        x_n *= x


def sin(x,n=10):
    return sum(take(n ,imap(lambda s,a,b: s * a / b,
                            signs(),
                            skip_even(x_n(x)),
                            skip_even(facts()))))

print sin(0)
print sin(math.pi/6)
print sin(math.pi/2)