Otro algoritmo típico donde los haya.
Esto de los años bisiestos ya se lo inventaron los romanos y otras culturas hace un montón de tiempo... ¿Para fastidiar? No... no del todo.
Resulta que nosotros tenemos muy asimilado que la Tierra tarda 365 días en dar la vuelta al Sol (lo que llamamos un año)... pero no es exactamente así. En realidad tarda 365 días y unas 5 horas y unos 48 minutos... y unos pocos segundos. Dicho de otra manera: tarda 365.2422 días.
Para cálculos astronómicos, esos decimales son muy importantes, pero a efectos de la fecha civil (la que utilizamos en la vida cotidiana) aplicamos un pequeño redondeo.
Como esos decimales representan casi un cuarto de día (unas 6 horas), resulta que cada cuatro años, la tierra ha tardado 365×4 días + 6 horas×4 → es decir, cada cuatro años hay que añadir un día al cómputo civil de los días... dado que en cuatro años, se han ido acumulando unas 6 horas por año más aparte de los 365 días.
Así pues, si un año es divisible por cuatro, se le añade un día más (nuestro querido amigo el 29 de Febrero)... Y eso es básicamente un año bisiesto... pero la corrección no queda ahí. Es necesario afinar un poco más. Resulta que no son seis horas exactas, sino que faltan algunos minutillos (unos 11)... así que para compensar esos minutillos, el último año de cada siglo (que termina en "00" y que debería ser bisiesto, porque si termina en "00" es divisible por 4) no será bisiesto... pero esta excepción no se aplicará, ademas, cada cuatro siglos. Con estos tejemanejes logramos, más o menos, que la fecha civil vaya acorde con la astronómica. Si no lo hiciéramos, empezaríamos a notar que las estaciones se van desplazando y empezando cada vez antes.
Aparte de éstas, son necesarias otras correcciones... debido, en principio, a que esa corrección no es del todo exacta y a que puede variar (la Tierra es bastante precisa en su recorrido, pero no es un reloj). Afortunadamente, los astrónomos se hacen cargo y nos van variando ligeramente la hora de vez en cuando sin que nos demos cuenta.
La palabra "bisiesto" proviene del latín "bisextus". El motivo es que antes de la aplicación del calendario gregoriano que utilizamos hoy en día (en el cual añadimos un día a febrero por el final), se duplicaba el 23 de febrero, que es el sexto día antes del comienzo (las calendas) de Marzo. Así pues, ese febrero tenía dos sextos días antes de las calendas de marzo: bi-sextus → bisiesto.
Después de este rollo, vamos a ver cómo podemos conocer algorítmicamente si dado un año del calendario gregoriano podemos saber si es bisiesto.
Es importante tener claro que este algoritmo funciona para fechas del calendario gregoriano ... ¿y qué es eso? Bueno... el sistema para medir las fechas civiles que utilizamos en occidente en la actualidad. Es necesario saber que aunque es un sistema muy extendido, no es el único que existe ahora mismo.
El calendario gregoriano fue adoptado por distintos paises en distintos momentos. En España se impuso en 1582, pero algunos paises, como Turquía, Grecia o Rusia lo adoptaron ya en pleno siglo XX.
A modo de resumen, podemos decir que se añade un día más (el 29 de Febrero) al calendario del año correspondiente si:
- Regla general: el año es divisible por cuatro.
- Con la siguiente excepción: Si el año es divisible por 100 y no por 400 no será bisiesto, aunque le corresponda por la regla general.
Al principio puede parecer un poco lioso, pero es más fácil de lo que parece. Basta comprobar si un año es divisible por 4... en ese caso, debería ser bisiesto... pero también hay que comprobar la excepción: si es divisible por 100 y no por 400 no lo será.
Para saber si un año es divisible por 4, basta con aplicar el operado módulo: "%" en C, C#, Java y compañía o "mod" en Pascal, Delphi y similares.
Se trata de un operador binario (que admite dos operandos) e infijo (que se coloca entre ambos operandos) y que devuelve el resto de la división entera entre el primer y el segundo operando.
Así pues, podemos elaborar un pequeño fragmento de código (En C#, como siempre) para comprobarlo:
bool EsBisiesto(int anno)
{
bool resultado;
//Comprobamos la regla general.
//Si anno es divisible por 4, es decir, si el
//resto de la división entre 4 es 0...
if (anno % 4 == 0)
{
//Si es divisible por 4, ahora toca comprobar
//la excepción
if (
(anno % 100 == 0) && //Si es divisible por 100
(anno % 400 != 0) //y no por 400
)
{
resultado = false; //entonces no es bisiesto
}
else
{
resultado = true; //No cumple la excepción.
//Lo dejamos como bisiesto por ser divisible por 4
}
}
else //Si no cumple la regla general
{
//No es bisiesto.
resultado = false;
}
return resultado;
} //EsBisiesto
Bufff... Bueno... seguramente funcionará... pero vaya rollo para comprobar tres simples condiciones.
Menos mal que sabemos un montón de lógica y lo podemos dejar mucho más sencillo, con una simple expresión booleana:
bool EsBisiesto(int anno)
{
//devuelve true si el año es múltiplo de 4 y
//no es multiplo de 100 pero no de 400
//false en caso contrario
return (anno % 4 == 0) && !(anno % 100 == 0 && anno % 400 != 0);
}
Quizá te estés preguntando qué es mejor... si utilizar un "if" o una expresión booleana... Bueno. La respuesta no es sencilla. El "if" conduce a un código más largo y quizá más complicado de entender (pero no para todo el mundo... quizá alguien lo prefiera). La expresión booleana, en principio, podría parecer más ineficiente, dado que parece que es necesario hacer varias operaciones para comprobar si el año es bisiesto, y en la solución con "if" si falla la regla general no se sigue comprobando más. Sin embargo, la mayor parte de compiladores e intérpretes modernos evalúan las expresiones booleanas aplicando una optimización conocida como cortocircuito, con lo cual, tampoco evaluarían todas las condiciones si falla la primera.
Además de todo esto... quizá hayas visto expresiones distintas a ésta para comprobar si un año es bisiesto (por ejemplo, en la Wikipedia )
En realidad, se trata de la misma expresión... solo que utiliza otras operaciones. El álgebra booleana, al igual que el álgebra con números tiene sus propiedades (asociativa, conmutativa, identidad... ) y algunas curiosas vueltas de tuerca (como las Leyes de Morgan) que hacen que distintas expresiones sean, en realidad, equivalentes.
Por ejemplo:
bool EsBisiesto(int anno)
{
return ((anno % 4 == 0 && anno % 100 != 0) || anno % 400 == 0);
}
|