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
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 moduledecimal
).– Luiz Vieira