expansiones infinitas

Para los que ya le han echado un ojo al problema anterior y han leido los comentarios sobre las expansiones (hey! recuerdo que si no habeis probado sin leer pistas primero es hacer trampa!) os dejo otro pequeño puzzler sobre el tema.

Imaginemos un trocito de codigo como:

double result1 = 3.65d + 0.05d;
float result2 = 3.65f + 0.05f;

Console.WriteLine(result1 == 3.7d);
Console.WriteLine(result2 == 3.7f);
Console.WriteLine(result1 == result2);

¿Sabríais decir cuál será la salida que obtendremos al ejecutar?

numeros bestias y descuentos

Que bonita esa cancion de los Maiden… 666, el numero de la bestia. Sin embargo, programanticamente hablando, el 666 es un numero de lo mas normalito (si lo ponemos  como 0x29A, 0o1232 o 0b1010011010 no impone el mismo respeto, verdad?)

Pero en programacion si que hay numeros «especiales» que son a la vez enormemente interesantes para los curiosos y terribles para los descuidados. En este articulo vamos a ver un par de puzzlers que espero que nos hagan pensar un par de veces la proxima vez que tengamos que evaluar estos «casos extremos» y de paso nos ayuden a repasar un poquito mas de aritmetica programante.

El primero, hablando de casos extremos, es para examinar unos conceptos basicos sobre matematica. Si tenemos este trocito de codigo que declara distintos valores y operaciones:

float zero = 0.0f;
float one = 1.0f;
float negativeone = -1.0f;

float division1 = zero / one;
float division2 = zero / negativeone;

float infinity1 = one / zero;
float infinity2 = negativeone / zero;

float division0 = zero / zero;

Console.WriteLine(division1 == division2);
Console.WriteLine(infinity1 == infinity2);

Console.WriteLine(infinity1 == infinity1);
Console.WriteLine(infinity2 == infinity2);
Console.WriteLine(division0 == division0);

¿Sabríais decir cuál será la salida que obtendremos al ejecutar?

Y el segundo es un caso de «depuracion pensando» que tiene que ver con numeros especiales tambien. Supongamos que tenemos una serie de productos a los que queremos aplicar un descuento (porque para eso estamos de rebajas de Enero). Tenemos algunos cuyo precio se ha reducido a la mitad, y otros que rebajamos un 10%. Como no nos gusta andar con la calculadora todo el rato nos hemos hecho un programita que aplica los descuentos por nosotros. El trocito de codigo que hace lo que queremos es algo como:

int[] precios = {20, 30, 20};
float[] descuentos = {0.5f, 0.5f, 0.1f};

for(int i = 0; i < precios.Length && i < descuentos.Length; i++) {
  int precioRebajado = (int) (precios[ i ] * (1 descuentos[ i ]));
  int porcentaje = (int) (100 * descuentos[ i ]);
  Console.WriteLine(«antes: {0} euros… ahora solo {1}!!! (-{2}%)»,
  precios[ i ], precioRebajado, porcentaje);
}

Sin embargo, al ejecutar nos hemos dado cuenta que la salida no es justo la que esperabamos. ¿Sabríais decir cuál es el error o errores que hemos cometido? ¿Como podemos hacer que nuestro programa funcione correctamente?

NOTAS/Actualizacion: Un par de apuntes sobre el problema de parte de un par de lectores avanzados (ver comentarios) }:)

  • Tal y como menciona Augusto, estos problemas pueden arreglarse usando la clase System.Decimal (o java.math.BigDecimal o el equivalente en cada plataforma). El tipo Decimal es bastante interesante, asi que dejamos aqui la referencia por si alguien es curioso y quiere adivinar por que sirve para este tipo de problemas (y cuales son sus ventajas e inconvenientes)
  • Curiosea que te curiosea, Tio_Luiso nos indica que en el primer trocito de codigo, C# parece que no representa el resultado de 0/-1 como «menos cero» (de acuerdo al estandar IEEE 754). En cuanto pueda informarme sobre esto pongo una actualizacion! }:)

Muchisimas gracias a los dos por tomaros el tiempo de compartir esta informacion! }:D

contando hacia atras

Vaya, este artículo debería haberlo publicado hace unos días, cuando muchos de vosotros sí que os estábais preparando para la cuenta atrás… de final de año, claro. Espero que me perdonéis, pero estoy un poco griposillo así que no me ha dado instancia a dedicar tiempo a escribir.


Aun así: ¡aprovecho para felicitaros a todos desde aquí y desear que los 0x757B12C00 milisegundos de este 2007 os sean propicios! }:)




El caso es que, continuando con el emocionante tema de los tipos de datos, he pensado en dejaros un pequeño puzzler para empezar el año. Os recuerdo que la idea de los puzzlers es responder a las preguntas sobre el código sin ejecutarlo primero (y si sois capaces ademas de saber qué hace, saber el por qué… ¡son gallifantes extra!)


Al igual que en el problema anterior, podéis publicar la solución en vuestro blog y enlazarla desde un comentario aquí o bien enviarlas directamente como comentario del artículo. En cualquier caso, intentaremos comentar la solución entre todos }:)


Pero basta ya de preámbulos: la idea es que tenemos estos tres pedacitos de código:








pedacito #1
int counter = (int)1e8;
while(counter > 0) {
counter–;
}
Console.WriteLine(«counter: « + counter);








pedacito #2
float counter = (float)1e8;
while(counter > 0) {
counter–;
}
Console.WriteLine(«counter: « + counter);








pedacito #3
double counter = (double)1e8;
while(counter > 0) {
counter–;
}
Console.WriteLine(«counter: « + counter);


¿Sabríais decir cuál será la salida de cada uno de ellos? Y ya puestos: ¿sabríais decir cuál tardará MENOS y cual MÁS en ejecutarse?


NOTA: tal y como estan expresados, estos pedacitos deberían ejecutarse sin problemas en C#, Java, C y C++ (simplemente cambiando la última línea por la llamada a System.out.println, printf o cout << apropiada). ¡Siento no haber podido hacer versiones en otros lenguajes!

empezando por el principio

Como en programancia101 estamos solo empezando, creo que lo más apropiado es empezar por el principio, pero claro, esto sería si hubiera un principio.


Lo ideal sería poder identificar cuál es la habilidad más importante que debe tener un desarrollador y decir: «¡aha! éste es el truco y éste es el problema que necesitáis para afinar la capacidad X». Pero esto creo que es un problema bastante difícil. ¿Cuál creéis vosotros que debería ser la habilidad número uno del buen programante?


Yo he sido incapaz de decidirme sólo por una, pero sí que he visto una actitud común en muchos programantes avezados: no se conforman con saber que algo funciona, sino que quieren saber por qué funciona, o por qué no funciona, o por qué funciona mejor en tal o cual caso. Saber este tipo de cosas está directamente relacionado con la curiosidad por conocer cómo maneja cada concepto «por dentro» nuestro lenguaje favorito, nuestro entorno, nuestro marco de trabajo…


Una de las típicas preguntas que suelen hacerse cuando se quiere comprobar qué tal maneja alguien los conceptos desde el principio es: ¿sabes darle la vuelta? Sí, exactamente, darle la vuelta a las cosas es un procedimiento poco usual en la «programación estándar», pero nos viene al pelo para empezar a proponer el que se vean las cosas de un modo distinto



Vamos a plantear esta pregunta a distintos niveles:



  • la idea más básica sería: ¿sabrías escribir un trozo de código que reciba una cadena de texto y le dé la vuelta? Es decir, si nuestra entrada es «abc», la salida sería «cba»
  • Bajando un poco más dentro de nuestros tipos de datos: ¿y un trozo de código que le de la vuelta a los bits de un byte? Es decir, si la entrada es 1, la salida sería 128
  • Y para terminar, uno un poco más complejo: en C# (y muchos otros lenguajes) los tipos flotantes se representan mediante el estándar aritmético IEEE 754. ¿Sabrías escribir un trozo de código que le de la vuelta a los bits del exponente y la mantisa de esa representación IEEE 754? Es decir, si la entrada es -118,625, la salida sería -17.180.580.000 (nota: en español la coma «,» es decimal y el punto «.» el separador cada 3 números de la parte entera)

Podéis poner vuestras respuestas, preguntas o ideas en los comentarios o bien poner un post con la solución en vuestro propio blog y dejar aquí un enlace (¡es mejor que mandármelas por mail, porque así todos podemos opinar!)


Preparados, listos… ¡ya! }:)

¿qué es programancia?

Si buscais en un diccionario «programación», os encontraréis con algo como: «acto de crear un programa de computadora, un conjunto concreto de instrucciones que una computadora puede ejecutar» (Wikipedia dixit)


Quiero empezar diciendo que este blog no trata de eso


Quiero decir, no trata de eso únicamente. Seguro que a algunos de vosotros os gusta programar. Quiero decir que os gusta mucho. Vamos, que os apasiona. Para vosotros, es posible que la definición anterior se quede un poco corta. Sí, el mecanismo de programar está contenido en esa definición pero… falta algo….


Programación en vuestra cabeza suena a reto, suena a crear algo fantástico que funciona a partir de la nada, sólo con ideas y líneas de código, suena a la lucha cuando las cosas no funcionan y a la sensación de triunfo cuando por fin das con el problema y todo encaja.


Aunque puede que me equivoque y para ti programar sea solamente eso que te obligan a hacer en tu trabajo, de 9 a 18 (con pausa para comer), y a lo que prefieres no dar muchas vueltas…


En ese caso, puede que este blog no te interese


Por supuesto yo intentaré convencerte de lo contrario. De que sí te interesa porque hay más cosas en la programación que escribir líneas sobre siempre lo mismo


Si me pidieran una definición para qué quiero decir con programancia yo diría que es algo como «el conjunto de técnicas, ideas y mecanismos de pensamiento que hacen del acto de crear programas una actividad creativa, divertida y útil».


Y es que tal y como yo lo veo, desarrollar aplicaciones es uno de los campos más intelectualmente estimulantes en la actualidad. ¿Conocéis muchos más campos en los que haya tantas posibilidades de probar nuevos conceptos, mejorar día a día y disfrutar de la sensación de haber realizado un trabajo que va a ahorrar trabajo a otras personas?


Programancia101 es un experimento que pretende que todos aprendamos un poco más sobre distintas formas de abordar problemas y/o practicar esas técnicas e ideas que a veces tenemos un poco olvidadas, pero que hacen del desarrollo algo mucho más entretenido.


Desde aquí iremos planteando distintos tipos de problemas interesantes, divertidos o simplemente que nos obliguen a revisitar conceptos que puede que nos sean útiles en un futuro (o que al menos nos sirvan para desconectar un poco y ver las cosas de un modo distinto) y comentarlos. Ejemplos de problemas que podrían ser interesantes son:



  • Programación genérica: a partir de una descripción, llegar al código para resolverlos (preferentemente en términos que nos permitan independencia del lenguaje)
  • Problemas de tipo «puzzler» en los que se presenta un trozo de código y se intenta que determinemos qué hace exactamente (sin ejecutarlo, claro)
  • Problemas de depurar pensando («debugging by thinking») en los que el código mostrado contiene errores y tenemos que localizarlos
  • Otras habilidades relacionadas con la programación, como trucos matemáticos o representación de datos.

Y por supuesto, estamos más que abiertos a recibir otras recomendaciones o sugerencias de actividades. Esto no sería ni la mitad de interesante si no os animáis a colaborar, proponer nuevas ideas y discutir los problemas entre todos. Yo haré lo que pueda por aportar mi granito de arena


Asi que… ¿qué me decís? ¿Os animáis a probar? }:)