ActiveState Code

Recipe 523018: sin, cos, tan for Decimal


Implementation of sine, cosine, tangent functions for Decimal arithmetic, using Taylor series expansion. It uses simple numerator and denominator generators.

The nice part is, the code is independent from the Decimal library. Feed it a float, it works just the same as if you feed it a Decimal (apart from the precision :-)

Python
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
from decimal import *
import math

pi = Decimal("3.14159265358979323846264338327950288419716939937510")

def gen_den():
    d = 1
    f = 1
    while(1):
        yield f
        d = d + 1
        f = f * d
    return

def gen_num(x):
    n = x
    while(1):
        yield n
        n *= x
    return

def gen_sign():
    while(1):
        yield 1
        yield -1
        yield -1
        yield 1
    return

def sincos(x):
    x = divmod(x, 2 * pi)[1]
    den = gen_den()
    num = gen_num(x)
    sign = gen_sign()

    s = 0
    c = 1
    i = 1
    done_s = False; done_c = False

    while(not done_s and not done_c):
        new_s = s + sign.next() * num.next() / den.next()
        new_c = c + sign.next() * num.next() / den.next()
        if (new_c - c == 0): done_c = True
        if (new_s - s == 0): done_s = True
        c = new_c
        s = new_s
        i = i + 2
    return (s, c)

def dec_sin(x):
    (s, c) = sincos(x)
    return s

def dec_cos(x):
    (s, c) = sincos(x)
    return c

def dec_tan(x):
    (s, c) = sincos(x)
    return s/c

print dec_sin(Decimal(1234))
print math.sin(1234)

Discussion

Use it with:

from decimal import *

dec_sin(Decimal("0.5"))

Comments

  1. 1. At 2:21 a.m. on 5 jul 2007, Gabriel Genellina said:

    Chebyshev polynomials may be faster. The problem with Taylor series in this case, is that it converges very slowly. A Chebyshev polynomial requires far less terms to obtain a desired precision, and can be generated using similar recurrence relations like your code for Taylor terms. See http://en.wikipedia.org/wiki/Chebyshev_approximation#Chebyshev_approximation

  2. 2. At 11:41 a.m. on 5 jul 2007, Raymond Hettinger said:

    Alternate recipes. Compare with the recipes already given in the docs:

    http://docs.python.org/lib/decimal-recipes.html

  3. 3. At 1:05 p.m. on 5 jul 2007, Alain Mellan (the author) said:

    Thanks. I should have Googled more before writing the code :-)

    OTOH, generators are fun!

Sign in to comment