Como calcular un seno o un coseno sin necesidad de una librería externa, sino por nuestros propios medios...
para esto haremos uso de las Series de taylor no caeré en detalles sobre esta teoría sino iré directamente a su aplicación... en este caso usaré solo la biblioteca iostream para impresión de datos
/*************************** cabecera ***************************/
Código
/****************************************************************/
#include <iostream> using namespace std; const double PI = 3.14159; const double EPSILON = 0.00001;
luego las series de Taylor para esto me solicitan 2 funciones puntuales, potencias y factoriales, para el caso de las potencias, solo necesito exponentes enteros, en los factoriales solo valores enteros (los que nos quita mucho trabajo de encima), aquí estan mi forma de aplicarlas (tambien un par de funciones extra, para conversión de grados a radianes y de modulo)
/*************************** funciones base ***************************/
Código
double angulos_a_radianes(double angulo) { return (angulo * PI) / 180; } double potencia(double base, int exp) { //si el exponente es 0 o la base es 1, el resultado es directamente 1 if(exp == 0 || base == 1){return 1;} //si la base es -1, el resultado es 1 o -1, para reflejar esto lo hago: //(si el exponente es par exp%2 es 0) 1 - (0)*2 = 1-0 = 1 //(si el exponente es impar exp%2 es 1) 1 - (1)*2 = 1-2 = -1 if(base == -1){return 1-(exp%2)*2;} //cargamos el resultado a la base double resultado = base; //siempre que el exponente sea mayor que 1 seguimos while(exp-- > 1){ resultado*=base; } return resultado; } long int factorial(int factor){ //el factorial de 0 es 1 if(factor == 0) return 1; //cargamos 1 para multiplicar long int resultado = 1; //hacemos... mientras factor sea mayor que 1 do{ resultado*=factor; }while(factor-- > 1); return resultado; } //retornamos como valor positivo siempre (función módulo) double positivo(double numero){ if(numero<0) return -1*numero; return numero; }
/*************************** funciones base ***************************/
ahora vamos a calcular directamente los valores que nos importa, seno, coseno y tangente
/*************************** funciones con taylor ***************************/
Código
//taylor para seno, con x en radianes double seno(double x){ //aqui llevaremos la sumatoria double resultado=0; //usaremos este valor de control para nuestra precisión double resultado_anterior=0; //este es el variable de la sumatoria int sumador = 0; //hacemos mientras la diferencia sea menor a la precisión do{ //almacenamos el resultado anterior resultado_anterior = resultado; //la serie de taylor resultado+= potencia(-1,sumador)*potencia(x,2*sumador+1)/factorial(2*sumador+1); //siempre avanzamos 1 sumador++; }while(positivo(resultado-resultado_anterior) >= EPSILON); return resultado; } //taylor para coseno, con x en radianes double coseno(double x){ //aqui llevaremos la sumatoria double resultado=0; //usaremos este valor de control para nuestra precisión double resultado_anterior=0; //este es el variable de la sumatoria int sumador = 0; //hacemos mientras la diferencia sea menor a la precisión do{ //almacenamos el resultado anterior resultado_anterior = resultado; //la serie de taylor resultado+= potencia(-1,sumador)*potencia(x,2*sumador)/factorial(2*sumador); //siempre avanzamos 1 sumador++; }while(positivo(resultado-resultado_anterior) >= EPSILON); return resultado; } double tangente(double x){ if(x/(PI/2)== (int)(x/(PI/2))){ cout << "Error: el angulo no debe ser multiplo de 90" << endl; return 0; } //trampa... pero la serie de taylor para tangente es computacionalmente muy pesada //este metodo aunque ligeramente menos preciso, resuelve el problema mucho más facil return seno(x)/coseno(x); }
/*************************** funciones con taylor ***************************/
y ya lo unico que queda por agregar es el main con la llamada a estas funciones, recomiendo mantener la precisión de cout en la misma cantidad de decimales de PI y EPSILON, ya que esto es lo que nos mantendrá en un "bonito" margen de precisión... tambien recuerden que si piden mucha precisión empezará a fallar por la forma en que funciona float a nivel binario en ese caso tendrán que usar aritmetica de precisión arbitraria (aquí un tema que hice sobre eso hace tiempo)
Código
int main(){ cout.precision(5); double calculo = angulos_a_radianes(30); calculo = seno(calculo); cout << calculo << endl; return 0; }
espero que les sirva!