elhacker.net cabecera Bienvenido(a), Visitante. Por favor Ingresar o Registrarse
¿Perdiste tu email de activación?.

 

 


Tema destacado: Sigue las noticias más importantes de seguridad informática en el Twitter! de elhacker.NET


+  Foro de elhacker.net
|-+  Programación
| |-+  Programación C/C++ (Moderadores: Eternal Idol, Littlehorse, K-YreX)
| | |-+  Calculando funciones trigonométricas sin librerías (series de taylor) (Aporte)
0 Usuarios y 1 Visitante están viendo este tema.
Páginas: [1] Ir Abajo Respuesta Imprimir
Autor Tema: Calculando funciones trigonométricas sin librerías (series de taylor) (Aporte)  (Leído 7,846 veces)
engel lex
Moderador Global
***
Desconectado Desconectado

Mensajes: 15.514



Ver Perfil
Calculando funciones trigonométricas sin librerías (series de taylor) (Aporte)
« en: 26 Octubre 2015, 16:56 pm »

Debido a una duda planteada por un usuario me decidí hacer este tema

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
  1. #include <iostream>
  2. using namespace std;
  3.  
  4. const double PI = 3.14159;
  5. 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
  1. double angulos_a_radianes(double angulo) {
  2. return (angulo * PI) / 180;
  3. }
  4.  
  5. double potencia(double base, int exp) {
  6. //si el exponente es 0 o la base es 1, el resultado es directamente 1
  7. if(exp == 0 || base == 1){return 1;}
  8.  
  9. //si la base es -1, el resultado es 1 o -1, para reflejar esto lo hago:
  10. //(si el exponente es par exp%2 es 0) 1 - (0)*2 = 1-0 = 1
  11. //(si el exponente es impar exp%2 es 1) 1 - (1)*2 = 1-2 = -1
  12. if(base == -1){return 1-(exp%2)*2;}
  13.  
  14. //cargamos el resultado a la base
  15. double resultado = base;
  16.  
  17. //siempre que el exponente sea mayor que 1 seguimos
  18. while(exp-- > 1){
  19. resultado*=base;
  20. }
  21. return resultado;
  22. }
  23.  
  24. long int factorial(int factor){
  25. //el factorial de 0 es 1
  26. if(factor == 0) return 1;
  27.  
  28. //cargamos 1 para multiplicar
  29. long int resultado = 1;
  30.  
  31. //hacemos... mientras factor sea mayor que 1
  32. do{
  33. resultado*=factor;
  34. }while(factor-- > 1);
  35.  
  36. return resultado;
  37. }
  38.  
  39. //retornamos como valor positivo siempre (función módulo)
  40. double positivo(double numero){
  41. if(numero<0) return -1*numero;
  42. return numero;
  43. }

/*************************** funciones base ***************************/

ahora vamos a calcular directamente los valores que nos importa, seno, coseno y tangente

/*************************** funciones con taylor ***************************/

Código
  1. //taylor para seno, con x en radianes
  2. double seno(double x){
  3. //aqui llevaremos la sumatoria
  4. double resultado=0;
  5.  
  6. //usaremos este valor de control para nuestra precisión
  7. double resultado_anterior=0;
  8.  
  9. //este es el variable de la sumatoria
  10. int sumador = 0;
  11.  
  12. //hacemos mientras la diferencia sea menor a la precisión
  13. do{
  14. //almacenamos el resultado anterior
  15. resultado_anterior = resultado;
  16.  
  17. //la serie de taylor
  18. resultado+= potencia(-1,sumador)*potencia(x,2*sumador+1)/factorial(2*sumador+1);
  19.  
  20. //siempre avanzamos 1
  21. sumador++;
  22.  
  23. }while(positivo(resultado-resultado_anterior) >= EPSILON);
  24.  
  25. return resultado;
  26. }
  27.  
  28. //taylor para coseno, con x en radianes
  29. double coseno(double x){
  30. //aqui llevaremos la sumatoria
  31. double resultado=0;
  32.  
  33. //usaremos este valor de control para nuestra precisión
  34. double resultado_anterior=0;
  35.  
  36. //este es el variable de la sumatoria
  37. int sumador = 0;
  38.  
  39. //hacemos mientras la diferencia sea menor a la precisión
  40. do{
  41. //almacenamos el resultado anterior
  42. resultado_anterior = resultado;
  43.  
  44. //la serie de taylor
  45. resultado+= potencia(-1,sumador)*potencia(x,2*sumador)/factorial(2*sumador);
  46.  
  47. //siempre avanzamos 1
  48. sumador++;
  49.  
  50. }while(positivo(resultado-resultado_anterior) >= EPSILON);
  51.  
  52. return resultado;
  53. }
  54.  
  55. double tangente(double x){
  56.  
  57. if(x/(PI/2)== (int)(x/(PI/2))){
  58. cout << "Error: el angulo no debe ser multiplo de 90" << endl;
  59. return 0;
  60. }
  61.  
  62. //trampa... pero la serie de taylor para tangente es computacionalmente muy pesada
  63. //este metodo aunque ligeramente menos preciso, resuelve el problema mucho más facil
  64. return seno(x)/coseno(x);
  65. }

/*************************** 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
  1. int main(){
  2. cout.precision(5);
  3. double calculo = angulos_a_radianes(30);
  4. calculo = seno(calculo);
  5. cout << calculo << endl;
  6. return 0;
  7. }

espero que les sirva!


« Última modificación: 26 Octubre 2015, 21:27 pm por engel lex » En línea

El problema con la sociedad actualmente radica en que todos creen que tienen el derecho de tener una opinión, y que esa opinión sea validada por todos, cuando lo correcto es que todos tengan derecho a una opinión, siempre y cuando esa opinión pueda ser ignorada, cuestionada, e incluso ser sujeta a burla, particularmente cuando no tiene sentido alguno.
furciorifa

Desconectado Desconectado

Mensajes: 94


Ver Perfil
Re: Calculando funciones trigonométricas sin librerías (series de taylor) (Aporte)
« Respuesta #1 en: 1 Noviembre 2015, 05:41 am »

Vaya excelente aporte, yo aportaré mis códigos, tengo un método numérico para calcular derivadas , integrales , y cosas poderosas sin librerías, espero que podamos sacar esta comunidad adelante, no hay una especie de chat es lo malo.


En línea

Páginas: [1] Ir Arriba Respuesta Imprimir 

Ir a:  

Mensajes similares
Asunto Iniciado por Respuestas Vistas Último mensaje
funciones trigonometricas
Programación Visual Basic
Gokuman 2 2,477 Último mensaje 22 Abril 2008, 18:53 pm
por Gokuman
Calculo integral. Series de Taylor (Ayuda)
Foro Libre
Nirvanareus 2 6,099 Último mensaje 8 Agosto 2010, 16:32 pm
por Constance
SERIES DE TAYLOR C++
Programación C/C++
anita0421 6 39,761 Último mensaje 17 Septiembre 2013, 05:12 am
por flony
Ayuda con el siguiente programa.
Programación C/C++
padiuwu 7 2,766 Último mensaje 3 Septiembre 2018, 15:48 pm
por Serapis
[C++] Series de Taylor: sen(x)
Programación C/C++
Zeta255 6 10,388 Último mensaje 26 Marzo 2021, 22:36 pm
por K-YreX
WAP2 - Aviso Legal - Powered by SMF 1.1.21 | SMF © 2006-2008, Simple Machines