Autor
|
Tema: Problema con ciclos (ejercicio de pi) (Leído 6,087 veces)
|
xuhipoint
Desconectado
Mensajes: 13
|
El ejercicio a programar es el siguiente: Desarrolla una función que calcule el valor de π a partir de una serie indicada a continuación, de la cual calcularemos la cantidad de términos indicados por el usuario. π = 4 – 4/3 + 4/5 – 4/7 + 4/9 - ... ± 4/n Mi idea fue crear el siguiente algoritmo: #include <iostream> using namespace std; int main (){ int b=0,a=1,i,c=0 ; int n; cout<<"Ingrese el numero"<<endl; cin>>n; if(n%2==0){ cout<<"numero invalido"<<endl; }else{ for(i=1;i<=n;i++){ if(i%2==0){ while(a<=n){ b=b-(4/a); a=a+2; } cout<<b<<endl; }else{ while(a<=n){ c=c+(4/a); a=a+2; } cout<<c<<endl; } } } }
Lo que no entiendo es porque no me da, según mi lógica y un pseudocodigo que hice eso debería funcionar...Por favor, podrían decirme en que me equivoque.
|
|
|
En línea
|
|
|
|
engel lex
|
uff una serie de errores XD... primero if(n%2==0){ cout<<"numero invalido"<<endl;
por que si es par es invalido? es una progresion, toma presicion al avanzar, la paridad no importa en valores altos... int b=0,a=1,i,c=0 ; for(i=1;i<=n;i++){ if(i%2==0){ while(a<=n){ b=b-(4/a); a=a+2; } cout<<b<<endl; }else{ while(a<=n){ c=c+(4/a); a=a+2; } cout<<c<<endl; } }
el error es que es una sumatoria.... una UNICA sumatoria.... tu lo que estás haciendo son 2 sumatorias... una negativa y otra positiva... para ambos debe ser "b" el valor afectado otra cosa... sabemos que pi es un numero decimal, especialmente esta operación requiere de decimales... si te fijas la haces con enteros.... jamás dará resultado... personalmente lo habría hecho así (super compacto XD) #include <iostream> using namespace std; int main(){ int precision, i = 0; float pi = 4; cout << "ingrese un grado de precision: "; cin >> precision; while (i++ < precision)pi += ((i%2==0?4:-4)/(1+i*2.0f)); printf ("\npi es: %.10f \n" , pi); system("pause"); return 0; }
desgloso un poquito: -en la división hago algo similar a if(i%2==0) { pi = pi + (4 / (i*2.0f) ); }else{ pi = pi - (4 / (i*2.0f) ); }
este 2.0f es para que se force como flotante el resultado de la división, si no, la división quedará como entero (por ejemplo si haces 4/i, al ser i entero, el resultado es entero) -en la impresión de datos no uso cout, sino printf con el valor "%.10f" esto significa que va a imprimir 10 decimales (aunque sean ceros) espero sea de ayuda inténtalo correr con un valor de 1000000000 mi maquina lo corre en unos 20 seg y el valor dudo que lo puedas tener más aproximado XD
|
|
« Última modificación: 29 Marzo 2014, 03:39 am 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.
|
|
|
leosansan
Desconectado
Mensajes: 1.314
|
El ejercicio a programar es el siguiente: Desarrolla una función que calcule el valor de π a partir de una serie indicada a continuación, de la cual calcularemos la cantidad de términos indicados por el usuario. π = 4 – 4/3 + 4/5 – 4/7 + 4/9 - ... ± 4/n .................................................. Lo que no entiendo es porque no me da, según mi lógica y un pseudocodigo que hice eso debería funcionar...Por favor, podrían decirme en que me equivoque.
* Para empezar las instrucciones:if(n%2==0){ cout<<"numero invalido"<<endl;
están de más ya que se puede pedir un número par de términos de la sucesión. Otra cosa es que los términos de la sucesión sólo contengan números impares, pero yo puedo pedir tres o cuatro términos.
* En:if(i%2==0){ while(a<=n){ b=b-(4/a); a=a+2; }
te sobra el while. Tal como lo tienes calcularías para cada i todos los términos de la sucesión. Y en el otro while lo mismo, además no tienes por cambiar el nombre de la variable, sigue usando b en lugar de c.
* Deberías declarar como float, ya que son valores que implican el cálculo de decimales, a las variables b y a.
* Te falta el return de la función main e indentar el código de forma correcta.
Con esto el código corregido y funcionando;
#include <iostream> using namespace std; int main (){ int n,i ; float b=4,a=3; cout<<"Ingrese el numero de terminos: "; cin>>n; cout<<endl<<endl<<"a["<<1<< "]= "<<b<<endl; for(i=1;i<n;i++){ if(i%2!=0){ b=b-(4/a); a=a+2; cout<<"a["<<i+1<< "]= "<<b<<endl; } else{ b=b+(4/a); a=a+2; cout<<"a["<<i+1<< "]= "<<b<<endl; } } return 0; }}
También podrías habar hecho un for que recorra sólo los impares y te ahorrarías un else y el uso del operador "%":#include <iostream> using namespace std; int main (){ int N,n,signo=-1 ; float b=1,i; cout<<"Ingrese el numero de terminos: "; cin>>n; N=2*n-1; for(i=3;i<=N;i+=2,signo*=-1) b+=(1/i)*signo; cout<<"Pi= " <<4*b<<endl; return 0; }
Ingrese el numero de terminos: 9
a[1]= 4 a[2]= 2.66667 a[3]= 3.46667 a[4]= 2.89524 a[5]= 3.33968 a[6]= 2.97605 a[7]= 3.28374 a[8]= 3.01707 a[9]= 3.25237
Process returned 0 (0x0)
Claro que si de lo que se trata es de calcular Pi y no es necesario imprimir cada termino del sumatorio, podrías hacer:#include <iostream> using namespace std; int main (){ int n,signo=-1 ; float b=1,i; cout<<"Ingrese el numero de terminos: "; cin>>n; for(i=3;i<=2*n-1;i+=2,signo*=-1) b+=(1/i)*signo; cout<<"Pi= " <<4*b<<endl; return 0; }
Ingrese el numero de terminos: 1000000 Pi= 3.1416
Process returned 0 (0x0) execution time
¡¡¡¡ Saluditos! ..... !!!!
|
|
« Última modificación: 29 Marzo 2014, 19:57 pm por leosansan »
|
En línea
|
|
|
|
Yoel Alejandro
|
Bueno, reconociendo el término general de la sumatoria (algo que siempre es bueno hacer): 4 * (-1)^n -------------- 2 * (n - 1)
para n desde 1 hasta infinito (o hasta el máximo N impuesto por el usuario), quedaría el código siguiente donde la idea (debida a leosansan en un post similar) de usar una bandera de signo que conmute de +1 a -1 en cada iteración nos evita tener que estar viendo si n es par o impar, quedaría: int main() { double numero; int n, N; int signo; cout << "numero de terminos: "; cin >> N; cout << endl; numero = 4; signo = -1; for ( n = 1; n <= N; i++, signo*=-1 ) { cout << "a[" << i << "] = " << numero << endl; numero += signo * 4. / (2*n + 1); } return 0; }
donde el punto en "4." obliga la división entre doubles en lugar de enteros (gracias de nuevo por la acotación leosansan).
|
|
|
En línea
|
Saludos, Yoel. P.D..- Para mayores dudas, puedes enviarme un mensaje personal (M.P.)
|
|
|
leosansan
Desconectado
Mensajes: 1.314
|
Amigo yoel_alejandro de corazón que todo es en plan buen rollo, nada de suspicacias, please!.
Antes que nada creo que se te fue un gazapo en la expresión:
...............................................................
4 * (-1)^n -------------- 2 * (n - 1)
..........................................
Creo que tu intención era poner: 4 * (-1)^n -------------- (2*n - 1)
Por otro lado:....................................... donde el punto en "4." obliga la división entre doubles en lugar de enteros (gracias de nuevo por la acotación leosansan).
Esta vez no me ha hecho falta lo del "4.", es decir lo del punto decimal, al declarar la variable i como float.
Por otro lado, al ser el mismo problema que en el otro tema del número Pi, he observado esta vez que me puedo ahorrar dos operaciones en cada ciclo del bucle for usando 1/i donde i es impar al empezar el bucle en tres e incrementar de dos en dos:.................................. N=2*n-1; for(i=3;i<=N;i+=2,signo*=-1) b+=(1/i)*signo; ......................................
que se corresponden con las que hacíamos en 2*n-1: una multiplicación y una resta en cada ciclo. Y teniendo en cuenta que para que la serie propuesta nos dé 3.1416 hay que tomar un millón, n=1 000 000, de sumandos, nos queda que con el nuevo for que propongo en el último mensaje, me ahorro dos millones de operaciones, de ahí que lo cambiará respecto del otro tema.¡¡¡¡ Saluditos! ..... !!!!
|
|
« Última modificación: 29 Marzo 2014, 20:36 pm por leosansan »
|
En línea
|
|
|
|
engel lex
|
tiempo de ejecucion... mi codigo... #include <iostream> #include <windows.h> #include <time.h> using namespace std; int main(){ int precision, i = 0; float pi = 4; cout << "ingrese un grado de precision: "; cin >> precision; clock_t tStart = clock(); while (i++ < precision)pi += ((i%2==0?4:-4)/(1+i*2.0f)); printf ("\npi es: %.10f \n" , pi); printf("Time taken: %.4fs\n", (double)(clock() - tStart)/CLOCKS_PER_SEC); system("pause"); return 0; }
numero introducido: 10.000.000 resultado: 3.1415970325 tiempo: 0.2270 (con 1.000.000.000 tarda 22 sec) codigo leosansan (modif para el tiempo) #include <iostream> #include <windows.h> #include <time.h> using namespace std; int main(){ int n,signo=-1 ; float b=1,i; cout<<"Ingrese el numero de terminos: "; cin>>n; clock_t tStart = clock(); for(i=3;i<=2*n-1;i+=2,signo*=-1) b+=(1/i)*signo; cout<<"Pi= " <<4*b<<endl; printf("Time taken: %.4fs\n", (double)(clock() - tStart)/CLOCKS_PER_SEC); system("pause"); return 0; }
numero introducido: 10.000.000 resultado: 3.1416 tiempo: 0.0980 ->anotacion... si metes 100.000.000 o más pasa más de 50 segundos sin hacer nada, me cansé de esperar el codigo de yoel_alejando (modificado un par de errores, con "n" e "i" y que solo haga una impresion final #include <iostream> #include <windows.h> #include <time.h> using namespace std; int main(){ double numero; int n, N; int signo; cout << "numero de terminos: "; cin >> N; cout << endl; clock_t tStart = clock(); numero = 4; signo = -1; for ( n = 1; n <= N; n++, signo*=-1 ) { numero += signo * 4. / (2*n + 1); } cout << "pi es: " << numero << endl; printf("Time taken: %.4fs\n", (double)(clock() - tStart)/CLOCKS_PER_SEC); system("pause"); return 0; }
numero introducido: 10.000.000 resultado: 3.14159 tiempo: 0.0960 (con 1.000.000.000 tarda 10 sec) el codigo de yoel_alejandro es el ganador quedó muy eficiente ya veo que hiperresumir todo no es tan bueno chicos usen printf es por el bien de todos o bueno de todos los decimales que fueron calculados en vano! XD
|
|
« Última modificación: 29 Marzo 2014, 21:06 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.
|
|
|
leosansan
Desconectado
Mensajes: 1.314
|
Es por pasar el tiempo, ¡ehh!.
Las salidas de leosansan, engel lex y yoel_alejandro por un millon, diez y mil millones, pero eso si en las mismas condiciones , incluso en el tipo de variables para lo que tuve que modificar mi código y declarar i como int, así estamos todos iguales:Como se ve estamos todos en un puño sin apenas diferencias. ¡¡¡¡ Saluditos! ..... !!!!
|
|
|
En línea
|
|
|
|
engel lex
|
leosansan XD lo hice por ocio XD pero a mi por alguna razon en todas las corridas la de yoel me daba unos 10 segundos menos que el mio en 1.000.000.000 y el tuyo no andaba en más de 10.000.000 D:
|
|
|
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.
|
|
|
leosansan
Desconectado
Mensajes: 1.314
|
El motivo que veo es que tenia declarada i como float. Al hacerlo como int todo va sobre ruedas.
Lo cierto es lo que comenté, estamos en centésimas de diferencias.
¡¡¡¡ Saluditos! ..... !!!!
|
|
« Última modificación: 30 Marzo 2014, 03:38 am por leosansan »
|
En línea
|
|
|
|
Yoel Alejandro
|
Vaya, ustedes sí que tienen ocio de ponerse a medir el tiempo con cada uno de los algoritmos, jaja! Bueno, yo uso la filosofía del mínimo recurso, me parece lo más lógico declarar n como entero, pues la función que realiza es la de un entero. Tengan en cuenta que comparar dos float es más complicado, a nivel de máquina, que comparar dos enteros. Los float llevan mantisa y exponente, y supongo que nivel de bits primero se comparan los exponentes, y si son iguales se pasa a las mantisas. En cambio en los enteros se comparan todos sus bits de una vez y punto. A pesar de ello yo hubiera supuesto que el manejo de leosansan, de sumar dos al contador n+=2 sería más eficiente que calcular 2*n+1 (suma y multiplicación incluida). Pero el ensayo demostró que fueron equivalentes, jeje, no se por qué. Por otra parte, es cierto que resumir el código fuente no necesariamente reduce el tiempo de ejecución. Para lo segundo hay que ponerse a pensar en lo que traduce el compilador, y por ende la manera como se ejecuta el código a nivel de la máquina (los tipos de datos involucrados, etc). Es un punto que precisamente yo venía sosteniendo desde otro post. Por supuesto, estas son cosas para entretenernos los usuarios más avanzados, no son cosas para considerar aún por la autora del tema quién está apenas comenzando a programar (algún día lo hará), jeje. Saludos a todos
|
|
|
En línea
|
Saludos, Yoel. P.D..- Para mayores dudas, puedes enviarme un mensaje personal (M.P.)
|
|
|
|
Mensajes similares |
|
Asunto |
Iniciado por |
Respuestas |
Vistas |
Último mensaje |
|
|
PROGRAMA USANDO CICLOS FOR
Programación C/C++
|
BOONE
|
5
|
8,709
|
7 Diciembre 2011, 04:22 am
por ISCJAIRO
|
|
|
lio con ciclos...
Java
|
dvdza
|
1
|
1,967
|
16 Diciembre 2012, 01:10 am
por kasiko
|
|
|
Ayuda Ejercicio c++ Ciclos Mientras y for
Programación C/C++
|
sergio011295
|
2
|
2,465
|
2 Mayo 2013, 16:13 pm
por NoLife
|
|
|
¿Cómo calcular los ciclos por instrucción en este problema?
Electrónica
|
xemnas
|
2
|
4,841
|
28 Octubre 2014, 11:17 am
por xemnas
|
|
|
Por favor ayúdenme, es un ejercicio de ciclos en python
Ejercicios
|
Ajrbar
|
2
|
3,597
|
3 Junio 2020, 19:16 pm
por MCKSys Argentina
|
|