1

Write a function that computes this expression, adding up terms until the absolute value of the next term is less than a specified tolerance tol or until at most nmax terms have been added.

I tried 'Import Decimal from Decimal' and float(c) but it did not work.

import math

def sin_taylor(x, tol=1e-7, nmax=100):

    b=0
    for i in range (nmax):
        e = float(2*i+1)
        c=float(math.factorial(e))
        #print(c)
        #print(b)
        a=((((-1)**i))*(x**(e))/c)
        b+=a
    return b

When I assert sin_taylor(0)==0, it gives 0 but when I assert math.isclose(sin_taylor(math.pi/2),0.999999943741051), it gives a=((-1)**i*d)/c OverflowError: int too large to convert to float

Ann Kilzer
  • 1,266
  • 3
  • 16
  • 39
Kisha
  • 11
  • 2
  • Take a look at [this answer](https://stackoverflow.com/a/16174565/1860768) to a similar question. It may help. – Ann Kilzer Oct 06 '19 at 00:32

2 Answers2

0

Try to convert numerics to decimal, like:

import math
import decimal


def sin_taylor(x, tol=1e-7, nmax=100):
    decimal.getcontext().prec = 90
    b=0
    for i in range (nmax):
        e = (2*i+1)
        c=(math.factorial(e))
        a = (-1)**i*decimal.Decimal(x)**(e)/c
        b0 = b
        b += a
        if b0 == b:
            print(i)
            break
    return b


print(sin_taylor(math.pi/2))
print(math.isclose(sin_taylor(math.pi/2), 1))
natter1
  • 354
  • 2
  • 10
  • @Kisha sorry, had to edit my solution, because I made a mistake with the equation a=... (I used 1 instead of i in one place). Now it should work. – natter1 Oct 06 '19 at 11:39
  • Also, regarding to @aparpara - he is right about b becoming too small. For your given tol=1e-7 thats most likly the only problem. On the other hand, if you want to have realy small tol-values (like 1e-100) you still might need to use decimal. But for that, you also need to change `decimal.getcontext().prec`- I will add it to my code. You can see the difference by adding print(i) inside the break-condtion suggested by aparpara and than try different values for `decimal.getcontext().prec`. – natter1 Oct 06 '19 at 14:33
0

First, I can't understand, why you believe sin(math.pi/2) should be close to 0.999999999943741051? Actually, it must be exactly 1.

Second, the most salient problem in your algorithm is that at some point a becomes so small that adding it to b changes nothing. If you break the loop at this point, you will not have these extra large values of c, like this:

def sin_taylor(x, tol=1e-7, nmax=100):
    b=0
    for i in range (nmax):
        e = float(2*i+1)
        c=float(math.factorial(e))
        #print(i, c, b)
        a=((((-1)**i))*(x**(e))/c)
        b0 = b
        b += a
        if b0 == b:
            break
    return b
aparpara
  • 2,171
  • 8
  • 23