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 :-)
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)
|
Use it with:
from decimal import *
dec_sin(Decimal("0.5"))
Tags: algorithms, generator
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
Alternate recipes. Compare with the recipes already given in the docs:
http://docs.python.org/lib/decimal-recipes.html
Thanks. I should have Googled more before writing the code :-)
OTOH, generators are fun!