Calculation of Sine with Python

Asked

Viewed 14,432 times

4

Hello, I have a problem in the sine calculus using Pyhton, I set up a function for the sine and cosene calculus, but the result is coming wrong for sine, while the cosene the result is right. I ended up discovering that sine works if I calculate with 60 degrees (my test was sen(30) and cos(60) where both should result in 0.5 or something close), my theory is that it works with values greater than 1 rad. here are the results in the console (sine(30) and cosene(60) respectively)

0.9909847665675204
-0.4999999999999262

and here are the codes

def converterGrausParaRad(numero):
    rad = (numero/180)*const_Pi()
    return rad
    #abaixo: definição da função seno por sin² + cos² = 1

def seno(numero):
    resultado = 0
    resultado = raizQuadrada(1 - (coseno(numero))**2)
    return resultado

#abaixo:definição da função coseno pela sua expanção da serie de taylor



def coseno(rad):
    numero = converterGrausParaRad(rad)
    cont = 0
    resultado = 0
    while(cont < 50):
        cont += 1
        resultado += (((-1)**cont)*(numero**(2 * cont)))/(fatorial(2 * cont))
    return resultado

1 answer

9


The problem is that the calculation of the cosine approximation is incorrect. If you observe the taylor series cosine, you will see that the value starts with 1 - but you start the variable resultado with 0. Just change to resultado = 1 that (this part) will work.

Then you’ll have another problem, related to precision. The approximation by this method generates some errors, and when cosine results in 1 it can occur from its function return 1.00000000000001. In this case, the root you try to calculate in the sine function will generate a complex number (since 1 - 1.00000000000001 will give a negative number). So another useful change is to round off the return of your cosine function in a few decimal places (I think 6 houses is fine).

The changed code follows below. But note that you did not prepare a functional example: many of its functions are not in the code. So, to test, I changed using the package math. The code, by the way, compares its calculation with those of the package math to illustrate the correctness.

import math

def converterGrausParaRad(numero):
    rad = (numero/180)*math.pi
    return rad
    #abaixo: definição da função seno por sin² + cos² = 1

def seno(numero):
    resultado = 0
    resultado = math.sqrt(1 - (coseno(numero))**2)
    return resultado

#abaixo:definição da função coseno pela sua expanção da serie de taylor

def coseno(rad):
    numero = converterGrausParaRad(rad)
    cont = 0
    resultado = 1 # ERRO!!!
    while(cont < 50):
        cont += 1
        resultado += (((-1)**cont)*(numero**(2 * cont)))/(math.factorial(2 * cont))

    return round(resultado, 6) # MELHORIA

angles = [i for i in range(0, 181, 15)]
for angle in angles:
    sin = seno(angle)
    cos = coseno(angle)
    sin_ = math.sin(converterGrausParaRad(angle))
    cos_ = math.cos(converterGrausParaRad(angle))
    print('ângulo: {} seno: {:.4f} ({:.4f}) cosseno: {:.4f} ({:.4f})' \
                .format(angle, sin, sin_, cos, cos_))

Upshot:

ângulo: 0 seno: 0.0000 (0.0000) cosseno: 1.0000 (1.0000)
ângulo: 15 seno: 0.2588 (0.2588) cosseno: 0.9659 (0.9659)
ângulo: 30 seno: 0.5000 (0.5000) cosseno: 0.8660 (0.8660)
ângulo: 45 seno: 0.7071 (0.7071) cosseno: 0.7071 (0.7071)
ângulo: 60 seno: 0.8660 (0.8660) cosseno: 0.5000 (0.5000)
ângulo: 75 seno: 0.9659 (0.9659) cosseno: 0.2588 (0.2588)
ângulo: 90 seno: 1.0000 (1.0000) cosseno: 0.0000 (0.0000)
ângulo: 105 seno: 0.9659 (0.9659) cosseno: -0.2588 (-0.2588)
ângulo: 120 seno: 0.8660 (0.8660) cosseno: -0.5000 (-0.5000)
ângulo: 135 seno: 0.7071 (0.7071) cosseno: -0.7071 (-0.7071)
ângulo: 150 seno: 0.5000 (0.5000) cosseno: -0.8660 (-0.8660)
ângulo: 165 seno: 0.2588 (0.2588) cosseno: -0.9659 (-0.9659)
ângulo: 180 seno: 0.0000 (0.0000) cosseno: -1.0000 (-1.0000)

If you’re going to use the general formula (it’s there on the same Wikipedia link), then accurate initiate the factor (cont) 0 (because -1 to 0 is 0, which is positive, and the calculation of the first interaction results in 1). Then, just move the line that adds 1 to the variable cont for after the calculation of the current factor:

def coseno(rad):
    numero = converterGrausParaRad(rad)
    cont = 0
    resultado = 0
    while(cont < 50):
        resultado += (((-1)**cont)*(numero**(2 * cont)))/(math.factorial(2 * cont))
        cont += 1 # MOVIDO P/ APÓS O CÁLCULO

    return round(resultado, 6)

Observing:

Your idea of switching the signal using -1 high to factor is well intelligent. : ) But keep in mind that the operator ** is computationally costly. A suggestion that should be more efficient is to do as follows (using the potentiation operator only once):

def coseno(rad):
    numero = converterGrausParaRad(rad)
    signal = -1
    resultado = 1
    factors = [i for i in range(2, 50, 2)]
    for f in factors:
        resultado += signal * ((numero ** f) / math.factorial(f) )
        signal *= -1

    return round(resultado, 6)
  • Thanks Luiz, the formula for the calculation I took from LEITHOLD vol 2 second edition page 590, I just got out of calculation 4 and wanted to try and I went to follow the book. sorry for not sending the functions I was frustrated with the code and I forgot (I’m new to the stack), about the result, I was wanting more precision, however I do not know how to manipulate the precision in python, do you have any material to indicate? thanks again!

  • 1

    Not at all. Maybe (depending on the accuracy you wish) you can manage by round I used over there. If not, you will need to use an approach such as the one described here: http://answall.com/questions/44715/como-rounder-um-float-em-python#comment239121_44715 (suggesting the module decimal).

Browser other questions tagged

You are not signed in. Login or sign up in order to post.