Colton Hancock
Colton Hancock

Reputation: 11

Using Machine Epsilon to approximate sin(x) using Taylor's Series

I am having a hard time using Machine Epsilon which is 2.220446049250313e-16,I then need to use abs error to determine if my abs value of my sine term is less than the Machine Epsilon.

Write a sine function using Taylor's Series to calculate the value of sin(x) where is the angle in radian. The angle must be between -(pi/2) and pi/2. Use Machine Epsilon to determine the number of terms that are required to calculate the value of sine.

I need to output the angle, my calculation of sine, the absolute error, and number of terms used. Here is what I have already:

def machineEpsilon(e):
    e = 1.0
    while(1.0 + e/2.0) > 1.0:
        e = e/2.0
    return e

def sine(x, n):
    sign = 1
    sine  = 0.0
    half_pi = math.pi/2
    #converts anything greater than pi/2 to something in between -pi/2 and pi/2
    while x > half_pi:
        x -= half_pi
    #converts anything less than -pi/2 to something in between -pi/2 and pi/2
    while x < -(half_pi):
        x += half_pi

    if x > math.pi:
        x -= math.pi
        sign = -1

    swap_sign = 1
    #loops through taylor series for sine

    for i in range(1, n * 2, 2):
        sine += swap_sign * (x ** i) / math.factorial(i)
        swap_sign *= -1

    return sign * sine

def main():
    numTerms = 0
    pie = math.pi
    angle1 = round(sine(-20, 50), 9)
    abbsErr1 = (abs(angle1 - math.sin(-20)))
    angle2 = round(sine((-pie), 10), 9)
    abbsErr2 = abs(angle2 - math.sin(-pie))
    angle3 = round(sine((-pie/2), 10), 9)
    abbsErr3 = abs(angle3 - math.sin((-pie/2)))
    angle4 = round(sine(-0.5, 10), 9)
    abbsErr4 = abs(angle4 - math.sin(-0.05))
    angle5 = round(sine(0.0000, 10), 9)
    abbsErr5 = abs(angle5 - math.sin(0))
    angle6 = round(sine(0.05, 10), 9)
    abbsErr6 = abs(angle6 - math.sin(0.0500))
    angle7 = round(sine(100, 5), 9)
    abbsErr7 = abs(angle7 - math.sin(100))
    print("\n")
    print("Name: Name")
    print("Machine epsilon = ", machineEpsilon(1))
    print("{:<12} {:<15} {:<25} {:<3}".format('Angle(rad)', '(my sine)', 'AbsErr',
                                              '# of Terms'))
    print("{:<12} {:<15} {:<25} {:<3}".format('-20.0000', angle1, abbsErr1, numTerms))
    #print(math.sin(-20))
    print("{:<12} {:<15} {:<25} {:<3}".format('-3.1416', angle2, abbsErr2, numTerms))
    #print(math.sin(-(pie)))
    print("{:<12} {:<15} {:<25} {:<3}".format('-1.5708', angle3, abbsErr3, numTerms))
    #print(math.sin(-(pie/2)))
    print("{:<12} {:<15} {:<25} {:<3}".format('-0.5000', angle4, abbsErr4, numTerms))
    #print(math.sin(-0.5))
    print("{:<12} {:<15} {:<25} {:<3}".format('0.0000', angle5, abbsErr5, numTerms))
    #print(math.sin(0))
    print("{:<12} {:<15} {:<25} {:<3}".format('0.0500', angle6, abbsErr6, numTerms))
    #print(math.sin(0.0500))
    print("{:<12} {:<15} {:<25} {:<3}".format('100.0000', angle7, abbsErr7, numTerms))
    #print(math.sin(100))
    print("\n")

Upvotes: 1

Views: 389

Answers (1)

vorrade -
vorrade -

Reputation: 114

Your sine function doesn't seem quite right - and it should also return the number of iterations required. I have taken your code and modified it to stop calculating when the current value of the series is the same as the previous one. (I also took the liberty of putting the values to calculate into an array and looping through them).

import math

def machineEpsilon(e):
    e = 1.0
    while(1.0 + e/2.0) > 1.0:
        e = e/2.0
    return e


def sine(x):
    sign = 1
    half_pi = math.pi/2

    #converts everything into range 0..2*pi
    while x >= 2*math.pi:
        x -= 2*math.pi
    while x < 0.0:
        x += 2*math.pi

    if x > math.pi:
        x -= math.pi
        sign = -1

    swap_sign = 1
    #loops through taylor series for sine

    i = 1
    sine  = 0.0
    oldsine = 1
    iterations = 0

    while sine!=oldsine:
        oldsine = sine
        sine += swap_sign * (x ** i) / math.factorial(i)
        swap_sign *= -1
        i += 2
        iterations += 1

    return (sign * sine, iterations) # value, number of iterations

def main():
    print("\n")
    print("Name: Name")
    print("Machine epsilon = ", machineEpsilon(1))
    print("{:<12} {:<22} {:<27} {:<3}".format('Angle(rad)', '(my sine)', 'AbsErr', '# of Terms')) 
    pie = math.pi
    values = [-20,-pie,-pie/2,-0.5,0.0,0.05,100]
    for v in values:
        s,numTerms = sine(v)
        abbsErr = abs(s - math.sin(v))
        print("{:<12} {:<22} {:<27} {:<3}".format(round(v,9), s, abbsErr, numTerms))
    print("\n")

if __name__=="__main__":
    main()

Upvotes: 0

Related Questions