jueves, febrero 28, 2013

Resolver el factorial de 100 no es "picar código"

Durante las pasadas navidades tuve que ayudar a un joven proyecto de Ingeniero Aerospacial con la "dura" asignatura de "Informática". Para aprobarla era necesario realizar cuatro prácticas, y la segunda de ellas se le había atascado a él, y a todo el resto de compañeros de su grupo. Habían preguntado a familiares que ya habían acabado la carrera de Ingeniería Aerospacial - con muy buena nota además - y a otros que estaban estudiando Informática, y estaban desesperados, por lo que como hay relación de familiaridad, decidieron pedirme ayuda a mí para acabar la práctica.

Hablamos un viernes por teléfono, para quedar en vernos el sábado siguiente, y durante esa llamada me contó cuál era esa práctica que tanto estaba costando a todos los miembros de su clase: Calcular el factorial de 100 sin perder ninguna cifra.
- "Pero hombre, si eso está chupado", contesté, "¿cuál es el problema?".
- "Que el compilador se rompe cuando va por treinta y algo".
- "No hombre, el compilador está bien, es que estás desbordando el tipo".

- "¿Qué es eso?", me dijo.
- "Ese es un problema típico de ingenieros, resolver las limitaciones", dije.
- "Bueno, mañana me lo cuentas", se despidió.
Al día siguiente nos citamos compilador mediante para que le ayudara a programar la práctica, dispuesto a explicarle que es un T.A.D. (Tipo Abstracto de Datos) y a ayudarle a codificarlo usando una lista en el lenguaje que tocara.
- "¿En qué lenguaje estáis programando?", dije esperando C, Java o Pascal.
- "Fortran", respondió.
Su puta madre pensé. Años oyendo hablar de este lenguaje y nunca me había tocado aprenderlo. En fin, que se le iba a hacer, tocaba aprender Fortran para codificar un TAD. No podía ser muy difícil.
- "¿Tienes un manual?", le inquirí
- "Sí, éste, pero no sé si será suficiente", me respondió.
Tras comprobar que explicaba como funcionaban los bucles, la definición de arrays enteros, la llamada a funciones y la impresión por pantalla concluí que era más que suficiente, así que abrí el editor de texto, le expliqué como iba el TAD y en menos de 100 líneas y 2 horas estaba codificado y resuelto el problema del factorial de 100 con todas las cifras.

Presentó la práctica, aprobó él y todos sus compañeros a los que les pasó la práctica y "se inspiraron en ella" para entregarla. Las dos siguientes prácticas que le quedaban también las hicieron, aunque de nuevo con estrategia grupal de manada, lo que concluyó con un bonito Sobresaliente en la asignatura sin haber pasado ningún examen.

Creo que los sobresalientes de mis notas en la universidad se pueden contar con los dedos de un pie - ya os leí parte de las notas en el discurso de la servilleta - , pero aprendí a programar bien y a disfrutar haciéndolo - a pesar de que en mi día a día no me toca hacerlo -, pero cuando estuve esas dos horas aprendiendo lo justo de Fortran para hacer la práctica me sentí como cuando lo hacía a diario. No se olvida.

Tras esto me acordé de por qué creo que este método de sólo trabajos está mal. Yo prefiero examinar a mis chic@s, obligarlos a estudiar un poco y "sufrir el trauma" de enfrentarse con un problema delante de una hoja en blanco.

Dicho esto, he de decir que os cuento toda esta historia por un motivo mucho más cercano en el tiempo: La selección de las becas Talentum para Zaragoza. Allí he entrevistado ya a más de 30 personas, la mayoría Ingenieros Informáticos e Ingenieros de Telecomunicaciones, y algunos me dijeron una frase que me llama mucho la atención: "Si hay que picar código, pues se pica".

No, no, no. Yo no quiero que piquéis código. Quiero que os sintáis como yo me sentía cuando veía a Los Programadores en TRON, siendo dioses capaces de crear vuestra propia tecnología. Programar no es un castigo. ¡Ni mucho menos! Es un don.

Cuando era un adolescente recuerdo pasarme horas programando los píxeles de la codificación ASCII para hacer animaciones en modo texto en Lenguaje C y disfrutar como un enano, o hacerme programas para calcular la quiniela, o simuladores de Ligas de Fútbol en los que los resultados eran simplemente valores RAND que veía como jornada a jornada cambiaban para obtener un equipo ganador distinto y saber quién era el campeón al final de la temporada.

No pienses que programar es "picar código" como algo despectivo, piensa en programar como algo maravilloso que te permite estar en el reducido grupo de los que pueden crearse sus herramientas.

Saludos Malignos!

73 comentarios:

Anónimo dijo...

¿Dónde está mi queso?

Anónimo dijo...

Programas pixeles ascii? Tambien lavadoras bosch?

Anónimo dijo...

100 lineas y 2 horas? Estas de broma o querias decir 10 lineas y 2 minutos? Soy programador fortran y me alarma que tengas una carrera donde aprendiste tanto de algoritmia como dices

Cyberkender dijo...

Oleeeeeee, pienso igualico. La programación permite realmente crear cosas que solamente existen en tu imaginación. Te da la capacidad de modelar una realidad existente o no a tu manera, sin practicamente límites.
Anónimo, si, se podía programar la matríz de pixeles de un carácter ASCII para luego emplear los caracteres para "dibujar". Yo... he visto cosas que vosotros no creeríais: Atacar naves en llamas más allá de Orión. He visto rayos C brillar en la oscuridad cerca de la Puerta de Tannhäuser. Todos esos momentos se perderán... en el tiempo... como lágrimas en la lluvia. Eso pero con los ordenadores....

Madrikeka dijo...

En mi trabajo, mis usuarios son en mayoría aeronáuticos y cuando les veo programando en Fortran, con Matlab, me estremezco del miedo...

Y mi grupo de desarrollo...todos con Java, y ellos no crean, pican código...y eso no hay dios que lo disfrute...

Lo de programar, dependen de donde te lo enseñen, por desgracia, a mi en el módulo, no me enseñaron a programar, me enseñaron a picar...y es por eso que lo detesto, pero creo que eso este año va a cambiar!

Me ha gustado mucho el post de hoy!!!

Anónimo dijo...

Enfrentarte a puzzles con 100 soluciones posibles y no descansar hasta encontrar la mejor. La satisfacción de encontrar el modo de enfrentarte a esa "feature" que te ha tenido blasfemando durante horas. El partir de un proyecto en blanco y ver cómo tu creatura va cobrando forma y vida.
Si, en ocasiones llega a ser frustrante. Y si, también muchas veces eres el último en la cadena de mando. Pero al final eres tu el que crea la funcionalidad o el programa.

La programación es una labor de artesanía, y mucho del creador queda impreso en la obra.
Si tienes la suerte de poder programar lo que quieras o lo que te gusta es una labor gratificante y nunca aburrida.

Un ingeniero que disfruta picando código.

Carlos Seco dijo...

Esa es la gran diferencia entre los que disfrutamos creando nuestros programas y nos metimos por vocación, de los que eran simplemente unos jugones y les atraían los ordenadores, que es totalmente distinto. El sentimiento que se produce cuando te pasas unas horas programando sin parar hasta que consigues lo que querías no tiene descripción.
Muy buen artículo

Anónimo dijo...

por un lado comparto, lo especial de programar para algunos es crear,es casi algo magico.
pero como dice el primer comentario
para otros muchos es picar codigo,
por necesidad , por donde esta mi queso,por lo que sea. Para ellos siempre sera ese despectivo picar codigo.
ademas la realidad laboral de nuestro bendito pais, es cruel con esto.
si vas a una entrevista o en tu propio trabajo , con cuarenta y muchos años y sigues programando, la pregunta que te hacen o se hacen es:¿que te ha pasado? pobre ja ja ja.
¿Vosotros veis muchos cuarentones-cincuentones programando?
¿creeis que esto cambiara?

Chema Alonso dijo...

@anónimo que se lo hace en 10 lineas y 2 minutos.

Supongo que tú eres de los que hubieras hecho el bucle y te hubiera dado el desbordamiento de tipos.

Yo tuve que hacerme un T.A.D. y para ello cree varias funciones para incializar el número como lista de enteros, para pasar un número entero a una lista de números enteros, para multiplicar listas de números enteros, etc...

No sé si llegaban a 100 líneas, pero te garantizo que hacerlo bien con todas las funciones y el programa principal eran algunas más de 10 líneas.

No seas bocazas y aporta algo de conocimiento si encimas sabes Fortran, y no vengas a decir tontadas.

Saludos!

Anónimo dijo...

Chema genio programador, un bucle for donde vas dividiendo entre 10 o 100 en cada iteracion y incrementando un contador que sera la potencia a la que se eleva el resultado del bucle. Te vuelvo a decir luser, en 10 lineas se hace sin problemas de tipos, no en 300 lineas como dices. Esque me daria verguenza hacer algo asi, y mas presumor de ello en tu blog como si fueras un genio de la programacion. Mejor dedicate al seo, que se te da bien

Chema Alonso dijo...

@anonimo, a ver si te enteras de que el Factorial de 100 es multiplicar 100*99*98... hasta 1.

No seas subnormal. No hay nada que dividir al principio, hay que multiplicar. Cuando vayas a trollear entérate de qué coño dices.

Saludos!

Cyberkender dijo...

@Maligno, @anonimo está tan orgulloso de si mismo que postea como anónimo... que querrá que no se sepa...

Anónimo dijo...

En cada iteracion multiplicas por x-1 y divides por 10, a su vez incrementas un contador que servira para elevar a la potencia del contador. Os ha quedado claro ahora a ambos dos o es necesario que lo explique para imbeciles?

Chema Alonso dijo...

@anónimo, tú si que eres imbécil. ¿Qué multiplicas en cada iteración? Tienes que tener el número almacenado y si lo mutiplicas se desborda.

Iteración 1:
Multiplicas 100*99 = 990
Divides por 10= 99
contador = 1
Imprimes qué? un 0?
Iteración 2 qué?

Las cifras que conforman el resultado dependen de la última multiplicación, ya sea por 2 o por 99, tienes que multiplicar un número muy gordo por 2 o por 99 para que te den las cifras del resultado.

Deja de insultar y trolear e intenta hacerlo "master".

Saludos!

Otro Del Sur. dijo...

Qué recuerdoooossss... lo siento, pero tengo que soltarlo... porque me trae grandes recuerdos.
Empecé programando en Basic por líneas, ya sabéis de 10 en 10 por si te olvidabas algo, que siempre te olvidabas algo XD. Pero luego me desvié de la fuerza, y mis hobbies crecieron y la programación fue desapareciendo hasta quedar como un buen recuerdo.
Recuerdo que en FP tuve que hacerle un programa a un compi, para el trabajo de su hermano, me tiré un mes programando y me lo pasé genial... y en la Universidad de Granada(que sólo hice el primer semestre) me encantaba programar en ODE, qué recuerdos, machacándome para ver cómo podía hacer esto o lo otro, creo que era a una de las pocas clases que iba, con el trabajo no tenía mucho tiempo, y para mi desgracia mis trabajos siempre se han separado de la programación... así que no he tenido mucha continuidad, salvo pequeñas cosas en casa. Lo último que recuerdo fue programar una función para excel 2003, porque mi director necesitaba una cosa que no entendía que "no se podía" hacer sin llamar a un programador, por eso me lo paso tan bien cuando leo estos blogs, por los buenos recuerdos que me traen.
Un saludo.

Anónimo dijo...

Te explico que es la potencia de 10 y su representacion? Veo que no lo pillas y seguiras sin pillarlo. Zanjo aqui la discusion. Suerte programando.

Pd: que chema programe foca y ponga a 20 compañeros de trabajo para 'darles visibilidad' #eshacking

Juanlu dijo...

Joe Anónimo, si son 10 líneas cuélgalas aquí que te quedará más corto incluso que algunos comentarios de la entrada y te sobrará tiempo para poner en evidencia a Chema :)

Chema Alonso dijo...

@anónimo capullo. Para saber las cifras las necesitas almacenar y multiplicarlas en cada iteración, por eso se hace el TAD de lista de números. Vas de star programando y no vales ni para troll.

Luser!

Chema Alonso dijo...

@anónimo troll, sigues siendo el mismo luser de siempre... Controla tu envidia...

Saludos!

Juanlu dijo...

Además este anónimo es un súper didáctico! Admiro su capacidad de oratoria. En un par de frases nos ha dejado a todos clarísimo cómo calcular el factorial de 100 en 10 líneas y dos minutos sin desbordamiento. De hecho se me ha ocurrido un pequeño ajuste y lo puedo hacer en 9 líneas y cinco segundos.

Venga Chema, si le pides perdón a Anónimo posteo aquí la solución :)

Otro Del Sur. dijo...

jummm... perdón por la intromisión... pero Maligno, creo que te equivocas en seguirle el juego, no porque tenga razón o no, sino porque consigue uno de sus objetivos, sacarte de tus casillas.
Supongo que uno de los pensamientos que tendrá será este: sólo he buscado en google... aunque también es cierto, que viendo los distintos Fortran que hay... ver este enlace http://caminos.udc.es/info/asignaturas/301/images/Imagenes_complementarios/1_Fortran.pdf donde se pueden encontrar varias programaciones, pero no dice que pueda o no haber desbordamiento, que es el gran error de muchas de las vulnerabilidades de este mundo, de programadores que no atendieron en clase, hace el programa y no lo depuran... pero eso sería una entrada aparte.
Un saludo.

Chema Alonso dijo...

@Otro del sur,

lo cierto es que si usas un tipo de datos en coma flotante no hay desbordamiento, pero se pierden cifras, es por eso que para sacar todas las cifras hay que usar una lista de enteros. Es un ejercicio típico de programación.

En cuanto al troll, es un viejo conocido de hace bastante tiempo ya, sé quién es y se retrata a sí mismo.

Saludos!

Anónimo dijo...

Desconozco la precisión que pueden tener los datos con coma flotante en Fortan. Pero si no me equivoco si se utiliza una base 100 en vez de una base 10 si no se pierde precisión si parece posible realizar el ejercicio sin necesidad de un T.A.D.
Me explico:

Partiendo de que el máximo nº de la serie es el 100 (100^1) si empezamos desde arriba.

result=100;

1ª iteración
result(100)*99=9900;
result=9900/100=99;
exp=1;

2ªiteracion
result(99)*98=9702;
result=9702/100=97.02;
exp=2;

3ªiteración
result(97.02)*97=9410.94;
result=9410.94/100;
exp=3;
...

Eso si, no me he parado demasiado a pensar cómo se va a mostrar el dato, por que si haces:

total=result*(100^exp);

el total se va a desbordar.
supongo que parseandolo a un String y contando posiciones sería posible(Como ya he dicho, ni la menor idea de Fortan).

Quizá se me escape algo pero de este modo la parte entera será cada vez menor y nunca se desbordará. Eso si, la parte decimal dará miedito(unas 200 posiciones...).

Parto del supuesto de que no hay pérdida de precisión y que va a soportar los 200 decimales. Si me he colado en algo por favor corregidme.

Un saludo ^_^.

Chema Alonso dijo...

@anonimo:

1.- La multiplicación total en entero desborda.

2.- El uso de float hace que se pierdan cifras (el factorial de 100 es un número muy gordo). 9.33262 * 10 elevado a la 157 para ser exacto.

3.- La única forma es alamcenarlo en un "string" o lista de números o array, y para ello tienes que multiplicar "strings", listas de núemros o arrays, es decir, hacer un TAD.

Estos ejercicios son de primero de carrera. Ponte a programarlo y nos cuentas.

Saludos!

Chema Alonso dijo...

@anónimo, lo de poner una parte decimal de 200 posiciones es lo que menos sentido he visto en programación en mi vida }:O

¿Si te entran 200 número después de la coma... por qué no te entran antes? }:O

El anonimo de los 200 dijo...

A mi también me resulta realmente raro que soporte 200 posiciones decimales pero has sido tú mismo el que has dicho:
"lo cierto es que si usas un tipo de datos en coma flotante no hay desbordamiento".

$Deity me libre de darle la razón al troll anónimo, era simple curiosidad.
Como he dicho 2 o 3 veces, ni idea de cómo funciona Fortan (y no hay ganas de ponerme a buscar un compilador ahora mismo, así que no creo que lo pruebe).

De todos modos, si cómo parece lógico, fortan no soporta 160 decimales resulta símplemente ridículo intentar calcularlo mediante una variable en la que de ninguna manera va a entrar el resultado.

Un saludo y no la tomes conmigo, sólo trataba de saber si era posible :(.

Anónimo dijo...

Hacerlo en Fortran era elección de los alumnos o imposición del profesor? Porque de fortran ni idea pero en js es muy sencillo conseguir los factoriales hasta 100 y almacenarlos:

var factorial = {1: 1}; for (var i = 2; i <= 100; i++) { factorial[i] = factorial[i-1] * i}; alert(factorial[100]);

Y en una linea! Alguien da mas? xD

Anónimo dijo...

Hola Anónimo :).

Creo que tienes razón.

Si no recuerdo mal js soporta más de 300 posiciones en un entero por lo que en teoría no existiría el problema que aquí se trata y no haría falta crearte tu propio tipo de dato.

Como curiosidad. Yo no almacenaría en un array todos los factoriales de los 100 primeros números cuando sólo necesito el último.

Y cada punto y coma cuenta como nueva línea :P. No hagas trampas ^_^.

De todos modos, muy bien elegido el lenguaje ;).

(De hecho lo he probado y funciona sin ningún problema :P)

Un saludo y un placer poder discutir el asunto.

Anónimo dijo...

Privacy PC guys have made a detailed transcription of Mr. Alonso’s talk at DEFCON: Owning Bad Guys and Mafia with JavaScript Botnets: http://privacy-pc.com/articles/owning-bad-guys-and-mafia-with-javascript-botnets.html

Otro Del Sur. dijo...

Entiendo que la gracia del ejercicio, sea precisamente esa... tener que currárselo, pensarlo de otra manera, porque entonces, posiblemente si fuera para js, el profe te diría calcula 200! y tendrías el mismo problema.

Novlucker dijo...

Esta claro el objetivo del ejercicio, la lógica por sobre el resultado.

En js puede que se desborde, en python te olvidas de esos problemas :)

>>> f = 1
>>> for n in xrange(200,1,-1):
f *= n
>>> f
788657867364790503552363213932185062295135977687173263294742533244359449963403342920304284011984623904177212138919638830257642790242637105061926624952829931113462857270763317237396988943922445621451664240254033291864131227428294853277524242407573903240321257405579568660226031904170324062351700858796178922222789623703897374720000000000000000000000000000000000000000000000000L

(solo como curiosidad)

Matix dijo...

ha no peliarse gente hay muchas formas de hacer un algoritmo, algunas mas eficientes que otras :) Saludos desde argentina!

Matix dijo...

No hay que paliarse gente, ha muchas maneras diferentes de realizar un algoritmo. algunas mas eficientes que otras, en fin con la tecnología de hoy en día no hay que preocuparse tanto por la optimizacion de este tipo, lo que importa es que funcione. Saludos =)

Anónimo dijo...

Matix escribes peor que la solución de Chema para obtener el factorial de 100

Daniel Paz dijo...

Este "Anonimo" es uno de los genius de la red pronto lo veremos haciendo preguntas estupidas en yahoo.

Newlog dijo...

Vaya trolleadas!

Programar no es picar código:
http://www.youtube.com/watch?feature=player_embedded&v=eBV14-3LT-g
https://www.youtube.com/watch?feature=player_embedded&v=nKIu9yen5nc

;)

aeroespacial dijo...

Hola!
Hace tiempo que sigo tu blog, pero hoy me atrevo por primera vez a comentar.

Tengo curiosidad por saber donde estudia aeroespacial el protagonista del desafio, en Madrid?

Respecto al uso de Fortran, las dos razones principales por
as que seguimos utilizandolo es porque en aplicaciones espaciales sigue siendo el lenguaje principal, y por su simplicidad, ya que se parece mucho al lenguaje normal. Quitando eso, si es una soberana pérdida de tiempo.


Muchas gracias, un saludo!


PD: ¿podrias colgar el codigo con el que resolviste el problema? tengo la impresion de que serà bastante didactico.

Anónimo dijo...

Como aprendizaje esta bien, pero llega un momento que todo estos lios de desbordamiento me sacan de quicio. Lo que quiero es obtener el factorial, no pelearme con la representación interna que ha elegido el lenguaje para almacenar el concepto de numero entero.

Cuanto más alto dea el nivel del lenguage, menos debería preocuparme de los detalles de la implementación del lenguaje.

Anónimo dijo...

Ostias tío creo que no debo de casarme con un solo lenguaje de programación y empezar a aprender algo nuevo :S

Anónimo dijo...

No estoy de acuerdo del todo con lo que dices, Chema. Desde un enfoque puramente académico tu método es el correcto, en el sentido de que es la manera "a bajo nivel" de hacerlo y es la respuesta que quería que se diera el profesor.

Ahora bien, desde un enfoque práctico (pongamos una empresa) no tendría ningún sentido hacer esto estando en 2013. Hace muchos años que existen lenguajes de MUY alto nivel que nos hacen la vida más fácil (de eso parece que no se han enterado en la universidad).

Por ejemplo Java. Ya tienes implementada la clase (el tad) que te lo hace (es la clase BigInteger) y se resuelve en pocas líneas y algunos minutos.

Pongamos ahora por ejemplo Python (o cualquiera de sus "vecinos" Ruby, Perl, etc.). Bien, en Python resulta que YA está implementada esta funcionalidad cuando se detectan números muy grandes, con lo qual la práctica en Python se hace en 1 minuto y 6 líneas, SÍ 6 LÍNEAS:

def fact(x):
res=1
for i in range(1,x+1):
res=res*i
return res

print(fact(100))

Y el resultado es el conocido 933262154439... que ya se ha comentado.

Es una prueba de lo mal que está la formación universitaria.
Tener una carrera ya no tiene demasiado valor por cosas como esta (lo digo como ingeniero informático). No tiene nada que ver con lo que te vas a encontrar en el mundo laboral o en la vida real.

¿Sabéis cuantas carreras pienso yo que debería haber? Pues unas cuatro o cinco (matemáticas, medicina, derecho, ciencias, filosofía y alguna más) y unas 4 o 5 universidades repartidas por toda España, exactamente igual que hace 300 años. Lo de ahora es de risa, es puro marketing, cada vez hay más especialización y más alumnos sin vocación, hay titulados que nunca han acabado un libro entero.

Si estáis pensando en ir a la universidad y leéis esto: NO VAYÁIS A LA UNIVERSIDAD, antes estudiad alguna lengua extranjera, viajad, leed mucho e intentad montar vuestro propio negocio de lo que os apasione.

Anónimo dijo...

Yo también era de los que en la adolescencia me ponía a editar los caracteres ASCII, pero no para hacer animaciones sino para hacer otras FONTs. Me acuerdo cuando en un libro de Norton leí que se podía hacer eso con interrupciones y me puse a probar hasta que dí con la manera.

También recuerdo que en esa época había un programita que a punta de ASCII animados te pintaban una escena inofensiva y luego a pisar una tecla te la animaban a lo porno, con su sonido 8bit correspondiente :P.

Pero no, yo no estudié informática ni nada de eso, pensé (y creo que no me equivoqué) que eso de vivir "picando código" en el mundo real iba a ser la peor condena que podía darle a mi vida.

Anónimo dijo...

Hay que ver la gente, pero que quereis? universitarios que resuelvan problemas o que se limiten a copy/pastear, la solución que aporta el maligno cumple los requisitos que supongo tendria el profesor de turno, que hay veces que damos palos a los profesores pero otras veces hay que darles la razon

Anónimo dijo...

Hay que ver la gente, pero que quereis? universitarios que resuelvan problemas o que se limiten a copy/pastear, la solución que aporta el maligno cumple los requisitos que supongo tendria el profesor de turno, que hay veces que damos palos a los profesores pero otras veces hay que darles la razon

Fernando dijo...

Me parece increíble que haya que piense que este ejercicio sea una perdida de tiempo... es justamente ese tipo de ejercicios que demuestran que se ha aprendido algo.

Yo suelo programar en PHP y tiene una librería para realizar cálculos con precisión arbitraria... sin embargo eso no me garantiza que la tenga disponible cuando la necesite por muchos motivos... el poder realizar ese tipo de cálculos de esa manera puede ser un método poco eficiente en general, pero puede resultar esencial si no dispongo más allá de las herramientas básicas.

En cualquier ingeniería te han de preparar para superar las limitaciones con lo que tengas, a lo McGyver pero en real ;D

Decir que en tal lenguaje o con tal herramienta se hace en una sola línea y en 1 minuto es no haber entendido nada y no saber dar una solución cuando las cosas se ponen feas.

Un saludo

Félix dijo...

Buenas noches. Es la primera vez que escribo, a pesar de seguir este blog desde hace un tiempo. Esta entrada me ha parecido muy interesante.

Lo primero, vaya por delante que no soy informático, sino matemático, y mis conocimientos en programación son básicos.

Dicho lo anterior, no entiendo a aquellos que dicen que en tal o cual lenguaje el resultado de las operaciones no se desbordan y que uno puede despreocuparse del tema. ¿Pueden decirme algún lenguaje en el que el cálculo de 1.000.000! no se desborde utilizando los tipos habituales? El que me plantea dudas es especialmente python, porque C, java, etc. si no voy equivocado se tienen unos rangos definidos para cada tipo. Lo pregunto desde el desconocimiento.

Está claro que el objetivo de la práctica no es calcular cuánto vale 100! Hay otras formas, utilizando otros lenguajes, que hacen más sencillo el programa. Sí. Pero es que en si nos ponemos en ese plan, para calcular eso no hace falta ni programar. 0 líneas de código de programación. Se lo pides por ejemplo a Wolfram Alpha y listo.
http://www.wolframalpha.com/input/?i=100!

El objetivo de esa práctica (gestión y evaluación de la misma aparte) parece que es ponerte ante una situación problemática de la que debes salir airoso. Y si 100! os parece algo innecesariamente fácil, coged el número tan alto como queráis y calculad el factorial. ¿No?

Un saludo.

Cyberkender dijo...

@Felix, En mi opinión, independientemente del lenguaje la idea de esta práctica, como la de muchas otras no es la utilidad de la misma, sino que el alumno sea consciente de los procedimientos a seguir para llegar a la solución. Por un lado darse cuenta de las limitaciones de la situación concreta teniendo en cuenta las caracteristicas de la herramienta a emplear (fortran en este caso). Por otro lado debe ser capaz de encontrar entre los conocimientos adquiridos una solución a esas limitaciones (estructuras, algoritmos...) y finalmente aplicarlo todo junto en una solución coherente. Si lo que piden es el cálculo de un factorial, o el descubrimiento de los números primos existentes entre dos dados creo que no es el problema principal sino la excusa...

Anónimo dijo...

Félix: Pues no. Los tiros no van por ahí. Aquí el tema es que los lenguajes de programación de alto nivel (los que se usan hoy día, vamos) llevan incorporadas muchas librerías con funciones muy comunes para que no tengas que volver a programar algo que alguien ya ha hecho (se llama reusabilidad de código). El ejemplo que mencionas sobre python y 1.000.000! demuestra que no has entendido el concepto.

Resulta que el problema de multiplicar números grandes no es nuevo. Eso significa que muchos programadores ya se han enfrentado a él y ya supieron como hacerlo. Por eso la solución del problema, la que da el "maligno", ya se ha guardado exactamente igual en las librerías, ya está implementada vamos.

Por eso no tiene sentido que preguntes que hubiera pasado si nos hubieran pedido 1.000.0000!, porqué tampoco se desborda, ¡básicamente porqué la librería de phyton implementa exactamente la misma idea de Chema!

Como curiosidad, té diré que 100.000! mi PC (un i5, sencillo vamos) lo calcula en 15 o 20 segundos. Y 1.000.000! ? Pues obviamente el ordenador se queda "pensando", supongo que tardará varias horas, pero lo importante es que no se desborda.

Ah y por cierto, ¿Cómo te piensas que lo calcula el Wolfram Alpha ese? Pues con un lenguaje de programación de alto nivel detrás de esa página que ya lleva incorporada la multiplicación mediante listas.

La primera cosa que hay que mirar al empezar un nuevo proyecto (o en la vida en general) son los "antecedentes", es muy probable que alguien ya haya tenido el mismo problema que tienes tú, por lo tanto ganaremos mucho tiempo si empezamos por ahí.

Te pondré un ejemplo, ya que dices que eres matemático. Imagina que te piden que intentes demostrar la conjetura de Goldbach (para los que no sepáis: "Todo número par mayor que 2 puede escribirse como suma de dos números primos") ¿que harías? Empezarías el problema de cero o aprovecharías todo lo que ya se ha hecho a lo largo de más de 250 años?

Félix dijo...

Anónimo, gracias por la aclaración.

En cuanto a lo que comentas de python, anoche no pude quedarme con la curiosidad y calculé 1.000.000!, tardó unos minutos (tampoco los conté, pero seguro que a la hora no llegó). Por curiosidad, ¿algún otro lenguaje puede hacer lo mismo de una manera tan sencilla como python sin desbordarse?

Estoy de acuerdo en que si tienes ese problema en tu vida profesional no vas a reinventar la rueda y lo más razonable es utilizar lo que ya está hecho. Pero disiento un poco en la vertiente educativa. Utilizo el ejemplo que tú has puesto. Antes de demostrar la conjetura de Goldbach, tengo que aprender a demostrar cosas que ya están demostradas por otros. Sin esa base es totalmente imposible que demuestre algo nuevo.

Por eso dije que interpreto el objetivo de la práctica de la que se habla aquí en un contexto de aprendizaje en el que debes afrontar una situación problemática. Que ya está resuelta, sí, pero por otros. No creo que a un nivel de formación inicial tengas que afrontar directamente problemas sin resolver antes de resolver problemas más asequibles.

Pero bueno, es mi opinión y puedo estar tan equivocado como cualquier otro.

Saludos.

Anónimo dijo...

En mi opinion el objetivo del ejercicio es simplemente, enfrentar al alumno a una limitación y obligarle a reconocer el problema que sabemos que tendrá para que busque una forma alternativa de resolver el ejercicio.

Es un problema mil veces resuelto y los lenguajes de alto nivel nos abstraen del mismo, pero ese no es el objetivo. El factorial de 100 no sirve para nada en este caso. Tan solo es una forma simple de obligar a buscar una solución a un problema en un ejercicio aparentemente tribial.

Personalmente me parece una práctica perfecta para realizar en una universidad dado que el objetivo no es obtener un resultado si no aprender a identificar y resolver un problema. Ya que en el mundo empresarial puede que calcular el factorial de 100 resulte tribial, pero problemas seguro que se encontrarán, y no siempre se podrán utilizar soluciones que ya estén hechas, y en estos casos resultará util haber tenido que realizar estos ejercicios que "no tienen sentido".

Un saludo

Dixon dijo...

Fué como leer mi propia historia.... solo que a mi si me toca programar en mi dia a dia..... pero la verdad pienso totalmente igual acerca de aprender a programar......

Lo peor es que en mi vida no ha sido un simple ingeniero Aeroespacial el que me ha pedido este tipo de favores.... sino Ingenieros de Sistemas :S ADV

Anónimo dijo...

A ver. No estoy diciendo para nada que el ejercicio no tenga sentido. Os doy totalmente la razón en que la idea de la práctica no es dar un resultado sino una resolución, un procedimiento. De todas maneras, a mí no me suele gustar enfrentarme a problemas ya resueltos (sobretodo cuando ya sé como se resuelven), me siento como que estoy haciendo una larga multiplicación a mano.

Dicho esto. En el caso particular de la informática, al ser una ingeniería, se valora mucho el tiempo y la eficiencia. Lo que realmente diferencia un buen programador de un "newbie" es precisamente que el buen programador reaprovecha mucho código, usando la POO (orientación a objetos, las famosas clases) y un prgramador novel hace programación "espaghetti", significa código sin ningún tipo de estructura, muy poco legible y además difícil de mantener. Me parece mucho más importante aprender a usar la API (conjunto de procedimientos y funciones) de un lenguaje de programación que poner problemas "clásicos" ya resueltos hace años.

La informática no es un área para estudiarla desde la teoría, como la física o la filosofía. Una hora de pelearse con un problema de la vida real vale más que 10 horas de conceptos teóricos, o de problemas clásicos ya resueltos en las API's de cualquier lenguaje moderno.

Imaginad un corredor de fondo intentando mejorar leyendo muchos libros sobre atletismo, sería mucho mejor que invirtiese ese tiempo corriendo, entrenándose para lo que se encontrará en la realidad.

Fernando dijo...

El tema es más real de lo que parece, hace unos años hice una pequeña utilidad en ensamblador que te decía el tamaño del disco duro... para eso tenía que hacer los cálculos pertinentes y tuve que implementar en ensamblador la manera de multiplicar números de 32 bits porque sólo disponía de registros de 16 bits...

Si un ingeniero no sabe solventar ese tipo de limitaciones y su solución es decir que para qué voy a buscar una solución si cambiando el hard/soft ya está solucionado... haz eso con un robot en Marte, hazlo anda.

Fernando dijo...

Ya como curiosidad, en PHP:
echo gmp_strval(gmp_fact(100)), "\n";
echo gmp_strval(gmp_fact(100000)), "\n";
echo gmp_strval(gmp_fact(10000000)), "\n";

Los tiempos:
0,0020s para 100!
1,7804s para 100.000!
138,1359s para 10.000.000!

No está mal.

Anónimo dijo...

Fernando: los lenguajes de alto nivel (e internet en general) han matado muchas cosas bonitas, no te niego que no fuese bello programar en ensamblador, fortran, pascal... Pero cuanto antes dejemos atrás la nostalgia mejor que mejor. Hay que adaptarse en el mundo que nos ha tocado vivir.

Siempre pongo de ejemplo un hombre que conozco que tenía de toda la vida una tienda de discos de música, todos sus colegas del gremio tuvieron que cerrar, obviamente no hacían más que quejarse y decir que internet era una basura y tal y cual. Él en cambio supo reinventarse y aprovechó la marca para montar un negocio online de varios productos relacionados, y le ha ido muy bien.

El desarrollo tecnológico tiene cosas buenas y malas, pero no podemos quedarnos en la nostalgia de cuando programábamos en fortran porque eso ha pasado a la historia.

Fon dijo...

Que recuerdos más malos me trae esto. Yo también hice esa informática.
Tengo una duda,¿lo intentasteis a lo bruto? En FORTRAN se puede cambiar el número de bits que se utiliza para el integer: http://gcc.gnu.org/onlinedocs/gfortran/SELECTED_005fINT_005fKIND.html
Con esto se resuelve con tres lineas.

Fon dijo...

program getfact100

! 100!=9.3e157
integer,parameter :: k550 = selected_int_kind(550)
integer(kind=k550) :: fact = 1
integer :: num

do num = 1, 100
fact = fact * num
end do

write(*,*) '100! = ', fact

end program getfact100

Fernando dijo...

Anónimo: sigues sin entender. No se trata de nostalgia, se trata de que en muchas ocasiones el entorno de producción tienes una limitaciones y ya.

Que el entorno de producción sea un servidor que no tenga habilitada la extensión GMP del PHP te limita y ya no puedes utilizar las cómodas y rápidas funciones gmp_fac... habrá ocasiones en las que tenga remedio (actualizar o instalar la extensión) y habrá otras en las que no... el ingeniero/técnico que triunfa es aquel que sabe adaptarse a las limitaciones.

De eso es de lo que habla Chema y de eso es de lo que hablo yo también.

El haber programado en tres ensambladores, Basic, Pascal, Logo, AppleScript, PHP, JS, C, AutoIt, PostScript (si, también se puede utilizar como lenguaje de programación)... me da unas herramientas que me permiten adaptarme a casi cualquier problema que me enfrente.

Utilizo la herramienta más adecuada en cada caso, si puedo, si no puedo elegir la herramienta soy yo el que se adapta.

Y no hay más, la práctica era para probar la astucia de los estudiantes, tenían que utilizar Fortran en un problema para el que no es el lenguaje más adecuado (aunque según han comentado es un lenguaje muy utilizado en el ámbito profesional de la carrera...) así que toca apañárselas con lo que hay.

Como digo, entrar a discutir esto me parece de malos programadores. Un buen programador resuelve el problema con lo que tiene, no se queja de lo que no tiene.

Un saludo

PD: A los anónimos: ¿tanto cuesta inventaros un nick para comentar?

Anónimo dijo...

Fernando, claro que entiendo lo que quieres decir, este discurso se ha repetido y se sigue repitiendo en las carreras de informática hasta la saciedad. El problema es que era válido hace 15 o 20 años, pero hoy ni de broma.

Las "limitaciones" que tu dices extisten sólo a un nivel didáctico-teórico o autoimpositivo.

En cuanto al software, puedes usar cualquier lenguaje de programación -de tan alto nivel como quieras- que es gratuito y compatible con muchas otras plataformas.

En cuanto al hardware, la rapidez de los procesadores ha crecido exponencialmente, igual que la capacidad de almacenamiento. La única limitación que puedes tener es tener que pagar por un hardware moderno.

Creo que estamos discutiendo de cosas diferentes. Tu hablas de la programación "teórica", la que se hace con lápiz y papel en pseudocódigo, la que te enseñaban en la universidad. Y yo te hablo de programación real, de implementar un programa en un lenguaje y un hardware determinados.

Nos guste o no, cualquier programa vamos a tener que implementarlo en un lenguaje concreto. No se puede dar como solución a un problema x líneas de pseudocódigo y decir que eso te daría la solución.

En matemáticas puedes dar como respuesta 3/7*pi+1 , en informática no, tienes que reponder 2.346

Cyberkender dijo...

Anónimo, nuevamente vuelves a pinchar. Los ingenieros se forman para aprender a enfrentarse a problemas. Eso de que puedes usar "cualquier lenguaje de programación de tan alto nivel como quieras" es falso, la mayoría de las veces es impuesto, y te debes apañar con los recursos que tengas. Y con el hardware lo mismo. Hardware no es solamente un PC que actualizas cuando quieres. A veces es un autómata, a veces es un micro para el que no existen entornos de desarrollo, a veces es una tarjeta inteligente, o todo junto, o algo nuevo y diferente. Yo creo que tu hablas de ingenieros "usuarios",pero la ingeniería es más que eso, mucho más, no te confundas.

Anónimo dijo...

Cyberkender, yo hablo de la realidad laboral en España, así de claro.

Esa ingenieía que dices (la de autómatas, robots que van al espacio, etc.) aquí no existe. Aquí el trabajo de un informático es automatizar tareas, posicionamiento en buscadores, gestionar una red, mantener un servidor, actualizar una web...

Es triste que en la universidad vendan ese discurso, pero es lógico, así los profesores no tienen que reciclarse y disponen de más asignaturas inútiles que enseñar.

Luego cuando la gente sale al mundo laboral se lleva una sorpresa, resulta que no saben hacer prácticamente nada de lo que piden y tiene que hacerlo el del módulo.

Cyberkender dijo...

Creo que aunque en España haya mucho de eso que tu dices, también hay muchíiisimo de lo otro. Los autómatas se utilizan en miles de empresas de este país. Un autómata no sólo es para ir a la luna, es para pintar coches y soldarlos en fábricas (en muchas ocasiones los programan los I.Industriales). Pero también hay muchos informáticos que pasan de mantener redes y se dedican a investigar. Que crean aplicaciones novedosas de auditoría de seguridad(véase FOCA). Que crean modelos diferentes de controlar la seguridad y se los compra google(VirusTotal), que idean un sistema de geoposicionar fotos y se lo compra google (Panoramio). Gente que va un día y mientras estudia se programa un Kernel (véase Toro) y no quiero extenderme, pero bueno. Al final cómo ya han dicho uno se define, hay picateclas y gente que resuelve problemas. Te recomiendo que aprendas a resolver problemas y entonces, sólo entonces, a lo mejor dejas de actualizar webs...

Anónimo dijo...

Las empresas que dices no están en España, ni tampoco los buenos salarios y las buenas condiciones laborales, están en Alemania o Estados Unidos.

Tal y como dices tú con todos esos ejemplos, la única manera de vivir dignamente de informático en España es siendo emprendedor.

He visto demasiada gente muy buena (probablemente mejor que tú y que yo) trabajar días enteros para cobrar muy poco.

Pero claro, es un tema delicado porque mucha gente ha puesto sus esfuerzos y esperanzas en un título que no sirve de mucho. Es lógico que les moleste que se digan esas cosas.

No te respondo a la última frase porque me gusta analizar las cosas desde un punto de vista general y realista, y no entrar en casos personales para ver "quién la tiene más larga".




Cyberkender dijo...

Anónimo, desde luego yo no estoy tratando de medir nada. Simplemente demuestro mi aprecio y utilidad a las asignaturas y prácticas que tuve que realizar. A su aparente inutilidad y a su cierta y verdadera utilidad para crear buenos ingenieros. Tal vez en algunas cosas la universidad se mueva un poco más lenta o debiese aplicar un poco más de practicidad. Pero en ningún caso creo que llevar a cabo resoluciones como la del artículo sobren.

kali_linux dijo...

El tema de la universidad hoy en día es un debate parecido al de los taurinos y antitaurinos, o en nuestro gremio los clásicos windows vs linux, ubuntu vs debian etc.

Son opiniones diametralmente opuestas y ya se ha dicho todo, yo ya me sé lo que me vas a decir y los argumentos que vas a dar, de la misma manera que tú ya sabes los míos. Obviamente no vamos a convencernos el uno al otro.

Saludos.

Fernando dijo...

Yo lo flipo con Anónimo... para empezar yo "sólo" tengo dos FPII (Electrónica Industrial y Electrónica de Equipos Informáticos) y trabajo desde hace unos quince años en un centro de impresión (una rotativa, para entendernos).

Mi trabajo real requiere enfrentarme día si y día también a equipos de los que no soy el administrador ni físico ni lógico: no se puede tocar ni hard ni soft.

El de mi compañero de mantenimiento es enfrentarse al mantenimiento de máquinas para las que no es posible tocar el hard o el soft (vaya, otra vez) y no contaré aquí las peripecias que ha de hacer para que las cosas sigan funcionando...

El de cualquier programador web consiste nuevamente en trabajar sobre plataformas en las que muchas veces no puede tocar ni hard ni soft....

Vamos, que por cada ejemplo que me des de trabajo real en España donde se pueda tocar hard y/o soft yo te doy diez de lo contrario.

Saludos

Anónimo dijo...

Bla, bla, bla...
¿Dónde está la implementación?
o tu no eres examinable...?

Chema Alonso dijo...

@anonimo ya lo han hecho muchas veces hasta que me saqué el doctorado. Ahora examino yo. Saludos!

Anónimo dijo...

Es que en una formación universitaria el objetivo no es calcular el número en cuestión en un lenguaje de alto nivel en el menor número posible de líneas, es adquirir la destreza de resolver un problema cuando te encuentras con limitaciones no previstas, como un desbordamiento de tipo. El problema no es "hallar un número muy grande", es "trabaja con números que desbordan la capacidad de trabajar directamente con números".

Anónimo dijo...

Yo hacía pantallas en pascal, y luego las llegué a hacer en C++ con ncurses en ambiente GNU/Linux. Lamentablemente no me decanté luego por la programación ni la seguridad pero no hay placer más grande que tener un programa 100% escrito por tí que compila y corre a la perfección (después de todos los errores que pasaste antes de llegar al compila y corre). Por cierto, leí uno de los comentarios donde ponía "100 líneas y 2 horas? o sea 10 líneas y 2 minutos" y se auto denomina programador en FORTRAN: Preocupante!

Andres Benavides dijo...

Saludos !

Busque esta entrada para compartirla con mis estudiantes, y como encuentro que no han enviado un código, les adjunto el proyecto que desarrollé en Java - NetBeans para calcular el factorial de 1.000, y una nota que me parece interesante.

https://github.com/benavidesarias/Factorial

Chema, no debiste exasperarte tanto, con los que no entienden el problema. Simplemente dejar que sigan estudiando informática, para entender como funciona un computador que tiene limitaciones en el numero de bits para representar un numero en el procesador. Mira que hasta hay matemáticos que no entienden el problema.

En cuanto al lenguaje de programacion, pues sabemos en entre mas bajo el nivel, mas complicado puede ser hacer algo que en uno de alto nivel. Se podría haber hecho en ensamblador, aplicándose las mismas estructuras de programacion: secuencias, ciclos y decisiones.

Javier dijo...

Programador se nace. El resto, picaores.

Sac dijo...

Maligno, yo tuve la fortuna de conocer un Argentino, de esos que en mi pueblo se suele decir {Esta tocado con una barita}, muy bueno en todo lo que hacía, su nick era Arm, nos conocimos en los apasionantes chat de IRC, desconocido para las nuevas generaciones.
Arm siempre me hacía me recordaba, que el código tenía que estar bien repartido en líneas, que las nuevas generaciones, hacían una mala práctica al escribirlo, que no separaban bien el código, que atestaban pocas líneas todo, me explicó que había una norma no escrita, por lo que había que separar bien el código, en tantas líneas como para que se pudiera leer claro y limpio, repartiendo en las suficientes líneas que necesitara, cuando nos topabamos con el código todo comprimido en pocas líneas, entraba en colera, por lo que entiendo, que tu también tienes esa buena actitud, lo separas bien, para su buena lectura y pensando siempre en si otra persona tiene que leerlo, además de lo limpio y aseado que queda.. ARM SIEMPRE ME DIJO QUE APRENDIERA PicoLisp. Por su simplicidad, aún no me metido a aprenderlo, pero si tu lo has utilizado, me encantaría saber tu opinión y algun consejo, pues eso Maligno, {Nuevas Generaciones, que no adoptan, las buenas costumbres de la vieja escuela} Abrazo Maligno, nunca me canso, de leerte y escucharte.. Gracias por tu gran labor.

Sac dijo...

Por cierto, todavía no he encontrado un buen manual de PicoLisp, para aprender.. Si alguien tuviera algo, lo agradecería, si fuese en Español, ya sería maravilloso, más videotutorial ojalá hubiera algo... Maligno si el videotutorial de Pico Lisp, fuese tuyo, sería un sueño.. Has usado este lenguaje alguna vez?, mi amigo Arm siempre me presionaba, con que aprendiera ese código, creo que es la única persona que conozco, que domina la tecnología informática como tu Maligno.. Abrazo hermano.

Entrada destacada

Desde HOY es BlackFriday en 0xWord.com Cupón 10% descuento: BLACKFRIDAY2024 y descuentos con Tempos de MyPublicInbox @0xWord @mypublicinbox

Pues este año tenemos el  BlackFriday  durante  7 días , y poco más que decir en el artículo que lo que he puesto en el título del artículo....

Entradas populares