Sine Calculation with Python

3

Hello, I have a problem in the sine calculation using the pyhton, I have set up a function for the sine and cosine calculation, however the result is coming wrong for the sine, while the cosine the result is right. I ended up finding that the sine works if I calculate at 60 degrees (my test was sin (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 on the console (sine (30) and cosine (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
    
asked by anonymous 15.01.2017 / 23:44

1 answer

8

The problem is that the calculation of the cosine approximation is incorrect. If you look at the Taylor series of the cosine, you'll 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.

There you will have another problem, related to precision. The approximation by this method generates some errors, and when the cosine results in 1 its function may return 1.00000000000001. In that case, the root you try to compute in the sine function will generate a complex number (since 1 - 1.00000000000001 will give a negative number). So another useful change is you round the return of your cosine function to some decimal places (I think 6 houses are fine).

The changed code follows below. But note that you did not prepare a working example : many of your functions are not in code. So, for testing, I've changed using the math package. The code, by the way, compares your calculation with those of the math package 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_))

Result:

â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 use the general formula (it's there on the same Wikipedia link), then need to start the factor ( cont ) at 0 (because -1 raised 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 in the variable cont to after calculating 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)
  

Note:

     

Your idea of switching the signal using -1 to factor is well   intelligent. :) But keep in mind that the ** operator is computationally costly. An   suggestion that should be more efficient is to do the following (using   the power-up 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)
    
16.01.2017 / 03:07