Há algum tempo, quando a bug_elseif ainda estava fazendo listas de exercícios em Python, apareceu um problema que envolvia verificar se um ano era bissexto ou não. Embora a construção de uma expressão para verificar se um ano é bissexto seja até intuitiva, como estávamos utilizando a condição invertida (verificar se o ano não era bissexto), sua construção não estava sendo fácil, porém é possível usar um pouco de matemática para chegar nela.
Construção da expressão
Primeiramente vamos construir uma expressão para verificar se um ano é bissexto. Para isso, ele deve ser múltiplo de 4, porém se o ano terminar com 00, ele também deve ser múltiplo de 400. Para verificar se um número termina com 00, basta verificar se ele é múltiplo de 100, e para verificar se um número é múltiplo de outro, podemos verificar o resto da divisão ou módulo (quem sabe falo sobre matemática modular em outro artigo), caso o resultado dessa operação seja 0, o primeiro número é divisível pelo segundo, e caso seja qualquer outro valor, o primeiro número não é divisível pelo segundo (ou não possui uma divisão inteira).
Assim, a expressão para verificar se o ano é bissexto pode ser construída como:
(ano % 4 == 0 && ano % 100 != 0) || ano % 400 == 0
A primeira coisa a ser observada é que existem duas subexpressões com o conectivo disjuntivo ("ou" ||
), ou seja, para um ano ser bissexto basta ele cumprir uma das duas condições (subexpressões). A primeira condição também é dividida em outras duas subexpressões, porém dessa vez com o conectivo conjuntivo ("e" &&
), assim é necessário que as duas condições sejam verdadeiras para que o seu valor seja considerado verdadeiro, onde a primeira verifica se o ano é divisível por 4 (resto da divisão é igual a 0), e a segunda verifica se ele não é divisível por 100 (resto da divisão é diferente de 0). Essa é a primeira possibilidade para um ano ser bissexto. A outra possibilidade é se ele for divisível por 400 (resto da divisão é igual a zero).
Assim, essa expressão retorna verdadeiro se o ano for bissexto, e falso caso ele não for.
Invertendo a expressão
Porém na ocasião, a expressão que estávamos usando deveria retornar verdadeiro caso o ano não fosse bissexto, e falso caso ele fosse bissexto (o contrário da expressão apresentada). Isso poderia ser feito negando a expressão anterior, ou escrevendo uma expressão de tal forma que retorne o oposto, e era justamente essa segunda opção que estávamos tentando fazer.
Entretanto, existe uma forma matemática de trabalhar com a negação da expressão, alteando-a até que ela chegue próximo ou a exata expressão que estávamos construindo. Isso é possível através de propriedades das operações boolianas, substituindo parte da expressão a cada vez que uma propriedade por aplicada. Sendo as mais comuns para esse tipo de operação as propriedades de negação da negação (!!a = a
), distributiva (a || (b && c) = (a || b) && (a || c)
e a && (b || c) = (a && b) || (a && c)
, que lembra a distributiva da matemática 2 * (3 + 4) = (2 * 3) + (2 * 4)
), e as leis de De Morgan (!(a || b) = !a && !b
e !(a && b) = !a || !b
). Para mais propriedades veja a página sobre o assunto na Wikipédia.
Para esse caso é necessário aplicar apenas as leis de De Morgan. Partindo da negação da expressão, aplicando-a passo a passo, temos:
!((ano % 4 == 0 && ano % 100 != 0) || ano % 400 == 0)
!(ano % 4 == 0 && ano % 100 != 0) && !(ano % 400 == 0)
(!(ano % 4 == 0) || !(ano % 100 != 0)) && !(ano % 400 == 0)
(ano % 4 != 0 || ano % 100 == 0) && ano % 400 != 0
Onde essa última expressão é a que precisávamos para o código.
Considerações
Álgebra booliana é interessante para trabalhar condições como de if
e laços de repetições dos códigos, seja para otimizá-la ou inverter os blocos de código do if
e else
, por exemplo, o que pode ser utilizado para deixar o código mais fácil de entender, colocando os blocos de código em uma ordem que faça mais sentido para a leitura. Ela também pode ser utilizada para facilitar a construção de expressões, como no caso apresentando, onde é muito mais fácil e intuitivo escrever uma expressão que verifica se o ano é bissexto do que um ano que não é, onde essa última pode até ser contraintuitiva, onde a álgebra booliana permite partir da expressão mais fácil para a mais difícil.
E para quem quiser se aprofundar nesse assunto, recomendo as aulas do RiverFount, que é professor de filosofia.