Como saber a fase da Lua de cabeça?

Quer aprender a descobrir a fase lunar de um dia apenas somando 3 a 4 números? Vamos ver mais a frente…

Ao estudar um pouco sobre as fases lunares, me deparei com um algoritmo muito interessante do matemático John Horton Conway. Ele cria um método para facilitar sabermos as fases lunares, sem a necessidade de cálculos elaborados, apenas com contas que conseguimos realizar mentalmente. Por isso, resolvi incrementar um pouco o algoritmo de fases lunares que eu havia feito e também implementar esse algoritmo mental. Se você ainda não viu a versão simplificada, para computadores, considerando somente o período sinódico, dê uma olhada aqui.

O algoritmo de Conway consiste em achar um padrão apenas utilizando contas simples para as fases lunares do século XX e XXI. Embora ele não tenha calculado os valores para os outros anos, creio que seja possível fazer apenas alterando um parâmetro na somatória final (tentarei posteriormente). A ideia desse algoritmo é que ele possa ser armazenado mentalmente para você saber as fases da lua, sem olhar para o céu.

Em resumo você considera apenas os dois últimos dígitos do ano, calcula o resto da divisão dele por 19 e se for maior que 9, subtraia 19. Multiplica o resultado por 11, calcula o resto da divisão por 30. Subtrai 4, para o século XX ou subtrai 8 para o século XXI e acha o resto da divisão por 30 novamente. Soma com o dia e o mês (se for janeiro ou fevereiro você soma 2). Se você achar difícil, olhe para o céu :D. Para o ano atual (2018), podemos já adiantar uma parte do algoritmo para facilitar o cálculo mental:

  • resto da divisão de 18 (dois últimos dígitos) por 19 é 18
  • como é maior que 9, subtraia 19; temos: 18-19 = -1
  • multiplica o resultado por 11; temos: -1 * 11 = -11
  • resto da divisão de -11 por 30 é 19
  • como estamos no século XXI, subtrai 8; temos 19 – 8 = 11
  • resto da divisão de 11 por 30 é 11

Essa a parte do cálculo que utiliza o ano. Então para o ano de 2018, você não precisa mais realizar nenhum cálculo, o valor obtido é 11 (pode decorar esse número, que até o fim desse ano ele é válido). Caso ache interessante, calcule para os outros anos. Para o dia e mês de hoje (05 de abril) é só fazer a seguinte conta:

  • número obtido (no caso é 11) + dia + mês; temos: 11+5+4 = 20
  • Se for janeiro ou fevereiro soma-se mais 2… não é o caso nosso

Com isso você só precisa saber o número 11 e somar com outros 2 números para saber o dia lunar que estamos. Que no caso é dia 20. Fácil, né? Para saber a fase da lua, você pode utilizar a seguinte tabela:

  • Lua Nova – 0, 1, 29
  • Crescente – de 2 a 6
  • Quarto crescente – 7 e 8
  • Crescente gibosa – de 9 a 13
  • Cheia – de 14 a 16
  • Minguante gibosa – de 17 a 21
  • Quarto minguante – 22 e 23
  • Minguante – de 24 a 28

Ou se preferir é só lembrar que quanto mais próximo do valor 15 estiver, mais cheia está a lua e assim não precisa decorar mais nada.

Com isso, resolvi implementar essa lógica do algoritmo, incrementando alguns valores. Ela pode ser encontrada aqui e aqui. O código está baseado na versão anterior (veja antes de utilizar o novo). Para a tabela de luas, criei uma função com condicionais (preciso melhorar):

[code language=”java”] public static MoonPhase getMoonPhaseConway(int lunarDay) {
if(lunarDay<=28) { if(lunarDay>=24) {
return MoonPhase.WANING_CRESCENT;
}
if(lunarDay>=22) {
return MoonPhase.THIRD_QUARTER;
}
if(lunarDay>=17) {
return MoonPhase.WANING_GIBBOUS;
}
if(lunarDay>=14) {
return MoonPhase.FULL_MOON;
}
if(lunarDay>=9) {
return MoonPhase.WAXING_GIBBOUS;
}
if(lunarDay>=7) {
return MoonPhase.FIRST_QUARTER;
}
if(lunarDay>=2) {
return MoonPhase.WAXING_CRESCENT;
}
}
return MoonPhase.NEW_MOON; //0,1,29
}[/code]

E o código da lógica:

[code language=”java” highlight=”18″] public static int getLunarDayConway(LocalDateTime ldt) {
var year = ldt.getYear();
var month = ldt.getMonthValue();
var day = ldt.getDayOfMonth();

if(year < 1900 || year >= 2100) throw new RuntimeException("Date must be greater than 1900 and less than 2100");
var centS = -4.0;
if(year > 2000) {
centS = -8.3;
}
var lastTwoDigits = year%100.0;
double vl = lastTwoDigits % 19;
if(vl > 9) {
vl-=19.0;
}
vl*=11.0;
vl%=30;
vl+=centS;

vl+=month+day;
if(month<3) {
vl+=2;
}

vl = Math.round(vl)%30;
return (int)((vl < 0) ? vl+30 : vl);
}[/code]

Da linha 7 a 17 é o cálculo do valor referente ao ano, que no nosso caso (2018) é 11. E na linha 18 é a soma que fazemos do mês e do dia para descobrir o dia lunar.

Sobre: Thiago Galbiatti Vespa

Thiago Galbiatti Vespa é mestre em Ciências da Computação e Matemática Computacional pela USP e bacharel em Ciências da Computação pela UNESP. Coordenador de projetos do JavaNoroeste, membro do JCP (Java Community Process), consultor Oracle, arquiteto de software de empresas de médio e grande porte, palestrante de vários eventos e colaborador de projetos open source. Possui as certificações: Oracle Certified Master, Java EE 5 Enterprise Architect – Step 1, 2 and 3; Oracle WebCenter Portal 11g Certified Implementation Specialist; Oracle Service Oriented Architecture Infrastructure Implementation Certified Expert; Oracle Certified Professional, Java EE 5 Web Services Developer; Oracle Certified Expert, NetBeans Integrated Development Environment 6.1 Programmer; Oracle Certified Professional, Java Programmer; Oracle Certified Associate, Java SE 5/SE 6