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!
– Guilherme Del Rio
Not at all. Maybe (depending on the accuracy you wish) you can manage by
roundI 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 moduledecimal).– Luiz Vieira