Autor
|
Tema: [C] e^x, si x es grande, numero negativo (Leído 5,759 veces)
|
edr89
Desconectado
Mensajes: 105
|
Hola, tengo que calcular el valor de e^x con la serie 1+x+((x^2)/2!)+((x^n)/n!)encontre un tema relacionado, el código descrito da el mismo resultado que el que yo he hecho. 1- No estoy seguro si he definido bien las variables 2- Para numeros muy grandes el resultado es falso, se arroja un numero negativo, leí en otro tema que se debe definir una funcion que permita numeros muy grandes (a la hora de calcular el factorial) porque la compilacion tiene un limite. ¿Se puede definir una variable mayor a long long? Como me ha sucedido en ocasiones anteriores, el programa funciona pero no tengo la certeza de que el código este bien escrito. Comentarios y sugerencias bienvenidas. #include <stdio.h> #include <math.h> main() { int e,respuesta,n; float resultado=0; printf(" Numero de terminos: "); for(e=n;e>1;e--) { resultado += (pow(respuesta ,n )) / (facto (n )); n--; } resultado += 1 + respuesta; printf("\ne^%d: %.4f",respuesta ,resultado ); } facto(long long int num) { int i=num; long long fact=1; for(i=num;i>1;i--) { fact*=i; } return fact; }
saludos!
|
|
|
En línea
|
|
|
|
leosansan
Desconectado
Mensajes: 1.314
|
Hola, tengo que calcular el valor de e^x con la serie 1+x+((x^2)/2!)+((x^n)/n!)
1- No estoy seguro si he definido bien las variables 2- Para numeros muy grandes el resultado es falso, se arroja un numero negativo, leí en otro tema que se debe definir una funcion que permita numeros muy grandes (a la hora de calcular el factorial) porque la compilacion tiene un limite.
¿Se puede definir una variable mayor a long long?
* Aparentemente as tienes bien definidas.
* Es el gran problema de C/C++, como el número entero tenga del orden de 20 cifras cruje, no da para más, sino prueba con 100 y 100 y veras.
* Tendría que repasar las nuevas librerías del estandar C99.
En todo caso el código que utilizas cojea en algunas cosas.
* Por ejemplo, cuando se trata de calcular e^x el número de términos ha de ser algo secundario ya que lo que en realidad interesa es calcularlo con una determinada precisión, y es esa precisión la que determina automáticamente el número de términos a tomar. En tu caso podrías entrar 3^10 tomando 10 sumandos y no tendrías una referencia de la precisión de ese cálculo.
* Otro detalle es la ineficiencia de la forma de calcular e^x, en el sentido que utilizas pow, que en si mismo no está mal, y sobre todo en la forma de calcular el factorial, culpable en números grandes- el factorial crece muy rápidamente- con la combinación de pow. Ambos juntos hace que a poco que crezcan los números y el número de términos de la serie a tomar obtengas resultados fuera del alcance o capacidades de C/C++.
* Un mejor método es tener en cuenta que e se calcula, utilizando el desarrollo en serie, de forma que cada nuevo sumando es el anterior multiplicado por un factor :x/n. Con este método alternativo no tienes ni que usar pow ni hacer el cálculo de factoriales previamente.
* Otra cosa a tener en cuenta es introducir una condición de precisión que determine de forma automática el número de sumandos a tomar.
* Y como último comentario a tu código, manejas pocos decimales para hacer cálculos de esta índole.
* También sería interesante comparar la diferencia entre el valor calculado con el valor exacto, entendiendo por éste el valor que de e^x daría la función e^x de la librería de math, que supongo hace uso de un algoritmo parecido al que te comento y paso a darte como variante del tuyo, y como muestra me da estas salidas:
Teclea el valor de x: 100 Valor estimado: 2.688117141816136e+043 Valor exacto: 2.688117141816136e+043. Error cometido: -1.525664384353662e+027 . Numero de terminos utilizados: 205 Teclea el valor de x: 500 Valor estimado: 1.403592217852838e+217 Valor exacto: 1.403592217852838e+217. Error cometido: -6.745532683619974e+200 . Numero de terminos utilizados: 716 Teclea el valor de x: 709 Valor estimado: 8.218407461554972e+307 Valor exacto: 8.218407461554972e+307. Error cometido: -1.900336232223e+291 . Numero de terminos utilizados: 964
Y el código para ello, que no se diga que no compartimos secretillos:/* e^x *la condición de finalización de las iteraciones: para este ejercicio utilizamos un bucle while y dos series (con los nombres serie y serie2 ) cuya diferencia mutua esta en un término,es decir, serie2 tiene un término más que serie1 . La razón de esta forma de calcular la serie la encontramos una vez más en la capacidad de almacenamiento de las variables tipo double : la fracción que calculamos y que añadimos a la serie es cada vez más pequeña y, por tanto, la diferencia entre las dos series también. Llega un momento en el que las cifras significativas que puede almacenar la variable no son apreciables y la fracción que sumamos no representa cambio en las variables: en ese momento las series toman el mismo valor, se igualan y, por tanto, se termina la ejecución del bucle*/ #include <stdio.h> #include <math.h> int main(void) { double x, serie1, serie2, frac; int i; while (1) { printf("Teclea el valor de x: "); scanf("%lf", &x); serie1=1.0; frac=x; serie2=serie1+frac; i=2; while (serie1!=serie2) { serie1=serie2; frac=frac*x/i++; serie2=serie1+frac; } printf("Valor estimado: %1.16g\n", serie2); printf("Valor exacto: %1.16g.\n", exp(x)); printf("Error cometido: %1.16g .\n", exp(x)-serie2); printf("Numero de terminos utilizados: %d\n\n", i); } return 0; }
* Existe otra variante para que el usuario indique la precisión con que quiere calcular e^x, pero eso te lo dejo como un simple ejercicio a partir del código anterior. Saluditos!. ... ..
|
|
« Última modificación: 3 Junio 2013, 07:34 am por leosansan »
|
En línea
|
|
|
|
flony
Desconectado
Mensajes: 584
|
hola sobre el tema de los números grandes, estaba buscando para que sirven los int8_t int16_t etc, y salio un tema interesante que lo conseguí de casualidad, dependiendo del nivel de precisión podrías usar algo llamado "punto fijo"...no se si sirva, pero para leerlo y ver si te sirve...acá una cosa que encontré referido al tema http://www.indicart.com.ar/seminario-embebidos/Elementos%20de%20C%20Embebido.pdf
|
|
|
En línea
|
si un problema no tiene solucion entonces no es un problema...es algo inevitable
|
|
|
leosansan
Desconectado
Mensajes: 1.314
|
hola sobre el tema de los números grandes, estaba buscando para que sirven los int8_t int16_t etc, y salio un tema interesante que lo conseguí de casualidad, dependiendo del nivel de precisión podrías usar algo llamado "punto fijo"...no se si sirva, pero para leerlo y ver si te sirve...acá una cosa que encontré referido al tema
Por lo que tengo entendido, no logras más allá de los veinte dígito, en enteros, de los que obtendrías con un long long int. Otra cosa es que las nuevas librerías del C99 permiten un mayor control en la declaración del tipo de enteros en cuanto a su precisión/número de dígitos.
Saluditos!. .... ..
|
|
|
En línea
|
|
|
|
bemone
Desconectado
Mensajes: 74
|
Perdon pero no lei mucho, leete el concepto de Sobrecarga de Funciones para poder utilizar el tipo acorde a tu situacion.
|
|
|
En línea
|
Odio los tipos de variable de Windows.
|
|
|
leosansan
Desconectado
Mensajes: 1.314
|
Perdon pero no lei mucho, leete el concepto de Sobrecarga de Funciones para poder utilizar el tipo acorde a tu situacion.
¿Sobrecarga de Funciones en C? . Creo que debes leerte mejor los post anteriores.
Saluditos! ... ..
|
|
|
En línea
|
|
|
|
edr89
Desconectado
Mensajes: 105
|
hola sobre el tema de los números grandes, estaba buscando para que sirven los int8_t int16_t etc, y salio un tema interesante que lo conseguí de casualidad, dependiendo del nivel de precisión podrías usar algo llamado "punto fijo"...no se si sirva, pero para leerlo y ver si te sirve...acá una cosa que encontré referido al tema http://www.indicart.com.ar/seminario-embebidos/Elementos%20de%20C%20Embebido.pdfGracias, lo reviso con tiempo. Teclea el valor de x: 100 Valor estimado: 2.688117141816136e+043 Valor exacto: 2.688117141816136e+043. Error cometido: -1.525664384353662e+027 . Numero de terminos utilizados: 205 Teclea el valor de x: 500 Valor estimado: 1.403592217852838e+217 Valor exacto: 1.403592217852838e+217. Error cometido: -6.745532683619974e+200 . Numero de terminos utilizados: 716 Teclea el valor de x: 709 Valor estimado: 8.218407461554972e+307 Valor exacto: 8.218407461554972e+307. Error cometido: -1.900336232223e+291 . Numero de terminos utilizados: 964
Perdon pero me cuesta trabajo entender el código, tengo que resolverlo con la formula 1+x+(x^n)/n!... por eso solo traduje a C usando la funcion pow y factorial. while (serie1!=serie2) { serie1=serie2; frac=frac*x/i++; serie2=serie1+frac;
La solucion como tal no la puedo dar usando la funcion exp, forzosamente tengo que usar la formula con factorial (aunque aqui esta solo como referencia) Me gusto mucho este otro código, lo reviso con tiempo. Yo estaba probando a hacerlo por partes para aprender a definir varias funciones y usarlas en main. gracias y saludos!
|
|
|
En línea
|
|
|
|
leosansan
Desconectado
Mensajes: 1.314
|
Gracias, lo reviso con tiempo. Perdon pero me cuesta trabajo entender el código, tengo que resolverlo con la formula 1+x+(x^n)/n!... por eso solo traduje a C usando la funcion pow y factorial. while (serie1!=serie2) { serie1=serie2; frac=frac*x/i++; serie2=serie1+frac;
La solucion como tal no la puedo dar usando la funcion exp, forzosamente tengo que usar la formula con factorial (aunque aqui esta solo como referencia) Me gusto mucho este otro código, lo reviso con tiempo. Yo estaba probando a hacerlo por partes para aprender a definir varias funciones y usarlas en main. La serie es: 1+1x/1 + x^2/ 1*2 + x^3/ 1*2*3 + x^4/1*2*3*4 + ....... Si observas cada nuevo sumando se obtiene del anterior multiplicando por una nueva x y dividiendo por un nuevo numero, que es justo el siguiente del último que se uso. Así la variable frac*x/i+1 irá dando:i=0 frac=0 i=1 frac=x/1 i=2 frac=x/1 * x/2 = x^2/ 1*2 i=2 frac=x/1 * x/2 * x/3= x^3/ 1*2*3Y así sucesivamente y la suma de frac dará el desarrollo en serio, Así de simple.Como aplicación de lo anterior y sin usar exp sino tomando, como tu habías propuesto, el número de términos:Teclea el valor de x: 1 Numero de terminos: 3 Valor estimado: 2.666666666666667 Teclea el valor de x: 10 Numero de terminos: 10 Valor estimado: 12842.30511463845 Teclea el valor de x: 1000 Numero de terminos: 100 Valor estimado: 1.190420382778621e+142
#include <stdio.h> #include <math.h> int main(void) { double x, serie=0, frac; int i, n; while (1) { serie=1; printf("Teclea el valor de x: "); scanf("%lf", &x); printf(" Numero de terminos: "); scanf("%d",&n); frac=1; for(i=0;i<n;i++) { frac=frac*x/(i+1); serie+=frac; } printf("\nValor estimado: %1.16g\n\n\n", serie); } return 0; }
Por lo que respecta al uso de funciones yo soy partidario de usarlas en casos de que se repita una parte del código, por ejemplo si estas calculando números combinatorios hay teóricamente que calcular tres factoriales, por lo que en este caso el uso de una función factorial nos evita repetir el código para calcular el mismo tres veces. O bien cuando entre varios se esté haciendo un código y queramos repartir la tarea, cada uno hará su parte como una función. Pero en estos casos tan sencillos me parece más oportuno estrujarse el cerebro buscando formas simples y más eficientes, como habrás visto con el uso de la variable frac.Saluditos! .... ..
|
|
« Última modificación: 7 Junio 2013, 13:35 pm por leosansan »
|
En línea
|
|
|
|
edr89
Desconectado
Mensajes: 105
|
Gracias!, ya lo entendi, la clave es: fact*=(x/n++);
y como dices me evito lo demas Saludos!
|
|
|
En línea
|
|
|
|
leosansan
Desconectado
Mensajes: 1.314
|
Gracias!, ya lo entendi, la clave es: fact*=(x/n++);
y como dices me evito lo demas Más exactamente:frac=frac*x/(i+1);
No confundir con:frac=frac*x/(i++);
ya que en este caso sólo se tomarían los términos pares de la serie, ya que en cada ciclo del for harían dos incrementos, el del for y el de la instrucción última.Saluditos desde Gran Canaria! .... ..
|
|
|
En línea
|
|
|
|
|
Mensajes similares |
|
Asunto |
Iniciado por |
Respuestas |
Vistas |
Último mensaje |
|
|
numero positivo y negativo en C++
Programación C/C++
|
rub'n
|
7
|
85,707
|
9 Julio 2010, 00:19 am
por rub'n
|
|
|
[Python] Qué número de los introducidos es el más grande...?
Python
|
sora_ori
|
5
|
5,936
|
18 Noviembre 2012, 14:17 pm
por sora_ori
|
|
|
indicar cual es el numero mas grande y pequeño
Programación C/C++
|
mort
|
3
|
10,610
|
5 Enero 2015, 02:00 am
por Yoel Alejandro
|
|
|
numero hexadecimal grande
Java
|
m@o_614
|
1
|
1,886
|
21 Enero 2015, 07:14 am
por 3n31ch
|
|
|
Leer un numero muy grande
Programación C/C++
|
mendez1415
|
1
|
2,059
|
26 Noviembre 2016, 18:07 pm
por engel lex
|
|