2010-03-26 202 views
29

¿Alguien sabe un algoritmo para calcular la fase lunar o la edad en una fecha determinada o encontrar las fechas para las lunas nuevas/llenas en un año determinado?Algoritmo lunar/fase lunar

Google me dice que la respuesta está en algún libro de Astronomía, pero realmente no quiero comprar un libro completo cuando solo necesito una página.

Actualización:

debería haber calificado mi declaración acerca de googlear un poco mejor. Encontré soluciones que solo funcionaban en algún subconjunto de tiempo (como los 1900); y las soluciones basadas en trigonometría que serían más computacionalmente costosas de lo que quisiera.

S Lott en su libro de Python tiene varios algoritmos para calcular la Semana Santa en un año determinado, la mayoría son menos de diez líneas de código y algunos funcionan para todos los días en el calendario gregoriano. Encontrar la luna llena en marzo es una pieza clave para encontrar la Pascua, así que pensé que debería haber un algoritmo que no requiera trigonometría y que funcione para todas las fechas del calendario gregoriano.

+0

El mismo problema estaba en que aquí manojos de veces ocultos en el problema de determinar la fecha de Pascua, pelusa, el Viernes Santo, y/o Pascua. – nategoose

+5

Un modelo astronómico preciso es inevitablemente complicado; el cálculo para la luna llena de la que deriva la fecha de Pascua (ver http://en.wikipedia.org/wiki/Paschal_full_moon) usa un modelo simplificado. –

+1

Un gran uso para el moon.py citado en la respuesta elegida es escribir una aplicación GUI (yo iría con GTK) para mostrar realmente la fase lunar con una imagen de la luna (en realidad estoy tratando de hacer esto, que se volvió considerablemente más fácil con esta pregunta y sus respuestas ...) – heltonbiker

Respuesta

15

He portado un código a Python hace un tiempo. Iba a vincularlo, pero mientras tanto, se cayó de la web, así que tuve que quitarle el polvo y subirlo de nuevo. Ver moon.py que se deriva de John Walker's moontool.

No puedo encontrar una referencia de esto a qué lapso de tiempo es exacto para ambos, pero parece que los autores fueron bastante rigurosos. Lo que significa que sí, usa trigonometría, pero no puedo imaginarme qué demonios usaría para eso, lo que lo haría computacionalmente prohibitivo. La sobrecarga de llamada a la función Python es probablemente más que el costo de las operaciones trigonométricas. Las computadoras son bastante rápidas en informática.

Los algoritmos utilizados en el código provienen de las siguientes fuentes:

Meeus, Jean. Algoritmos Astronómicos. Richmond: Willmann-Bell, 1991. ISBN 0-943396-35-2.

A imprescindible; si solo compras un libro, asegúrate de que sea este. Los algoritmos se presentan matemáticamente, no como programas de computadora, pero el código fuente que implementa muchos de los algoritmos en el libro puede pedirse por separado al editor en QuickBasic, Turbo Pascal o C. Meeus proporciona muchos ejemplos de cálculos que son esenciales para la depuración su código, y frecuentemente presenta varios algoritmos con diferentes intercambios entre precisión, velocidad, complejidad y validez a largo plazo (siglo y milenio).

Duffett-Smith, Peter. Astronomía práctica con su calculadora. 3ª ed. Cambridge: Cambridge University Press, 1981. ISBN 0-521-28411-2.

A pesar de la palabra Calculadora en el título; esta es una referencia valiosa si está interesado en desarrollar software que calcule posiciones planetarias, órbitas, eclipses y similares. Se proporciona más información de fondo que en Meeus, que ayuda a aquellos que no están versados ​​en astronomía a aprender la terminología a menudo confusa. Los algoritmos proporcionados son más simples y menos precisos que los proporcionados por Meeus, pero son adecuados para la mayoría del trabajo práctico.

+14

"Las computadoras son bastante rápidas en informática". - ¡Lo amo! Puede que tenga que citar ese. –

+0

Bueno, estoy trabajando en un sistema de calendario para Oracle y Postgres. Quiero poder encontrar fechas basadas en la fase lunar. Y eso podría significar realizar este cálculo en un montón de fechas. Y computacionalmente costoso = visita del DBA. :) –

+0

Lo importante aquí, por supuesto, es que el código de Keururn y el código de John Walker contienen referencias a fuentes autorizadas contra las cuales se puede verificar su código. Estas fuentes se enumeran [aquí] (http://www.fourmilab.ch/moontoolw/moontool16.html). – Richard

11
+2

@Jack: ¡WOW! +1 ... La memoria. No podría decir de dónde sabía ese nombre: "Ben Daglish". Fue uno de los mejores (dije * uno *;) compositor de música de 8 bits en el C64 en aquellos días. Es sorprendente encontrar un enlace a él para algo completamente diferente (tuve que buscar en su sitio web hasta que encontré los enlaces de C64 para recordar de dónde sabía ese nombre). – SyntaxT3rr0r

+5

-1 Una de las buenas características de StackOverflow es que las personas pueden venir aquí para obtener respuestas, en lugar de enlaces a las respuestas. Además, su enlace superior está roto, su segundo enlace no tiene citas para convencer a un programador cuidadoso de que los algoritmos enumerados en él son correctos, su tercer enlace tiene citas, pero el código ha sido alterado de los originales. El cuarto enlace es igualmente problemático. – Richard

+1

¿De quién es Google? Los éxitos son REALMENTE diferentes para diferentes personas. – jkj

-1

Una rápida de Google reveló this.

+0

Encontré esto, lo cual es misteriosamente más fácil aunque muy similar a los resultados de moon.py (respuesta elegida). – heltonbiker

+1

-1 Una de las buenas características de StackOverflow es que las personas pueden venir aquí para obtener respuestas, en lugar de enlaces a las respuestas. Además, el código al que se vincula no tiene referencias para convencer a un cuidadoso programador de que es correcto. – Richard

0

Sé que estás buscando Python pero si puedes entender C# hay un proyecto de código abierto allí llamó Chronos XP que hace esto muy bien.

+0

Puedo leer casi cualquier cosa además de Perl. LOL. Pero Chronos XP parece ser más una aplicación de astrología que astronomía. –

+1

Mire en el archivo llamado LunarPhase.cs. Esa clase básicamente hace lo que dice que hace. Es una de las mejores implementaciones que he encontrado, lo cual es desafortunado porque todavía es complejo. Si no desea descargar todo el código fuente, haga una búsqueda de ese nombre de archivo en Google Code. –

-1

Si no necesita alta precisión, siempre puede (ab) utilizar una clase de calendario lunar (o lunisolar) (por ejemplo, HijriCalendar o ChineseLunisolarCalendar en Microsoft .NET) para calcular la fase lunar (aproximada) de cualquier fecha , como la propiedad "día del mes" del calendario, siendo un día calendario lunar (o lunisolar), siempre corresponde a la fase lunar (por ejemplo, el día 1 es la luna nueva, el día 15 es la luna llena, etc.)

+3

-1 por mencionar .NET – klemens

10

Si eres como yo, intenta ser un programador cuidadoso. Por lo tanto, te pone nervioso cuando ves código aleatorio disperso por Internet que pretende resolver un problema astronómico complejo, pero no explica por qué la solución es correcta.

Cree que debe haber fuentes autorizadas como libros que contienen soluciones cuidadosas y completas. Por ejemplo:

Meeus, Jean. Algoritmos Astronómicos. Richmond: Willmann-Bell, 1991. ISBN 0-943396-35-2.

Duffett-Smith, Peter. Astronomía práctica con su calculadora. 3ª ed. Cambridge: Cambridge University Press, 1981. ISBN 0-521-28411-2.

Confíe en las bibliotecas de código abierto ampliamente utilizadas y probadas que pueden corregir sus errores (a diferencia de las páginas web estáticas). Aquí, entonces, hay una solución de Python para su pregunta basada en la biblioteca PyEphem, usando la interfaz Phases of the Moon.

#!/usr/bin/python 
import datetime 
import ephem 

def get_phase_on_day(year,month,day): 
    """Returns a floating-point number from 0-1. where 0=new, 0.5=full, 1=new""" 
    #Ephem stores its date numbers as floating points, which the following uses 
    #to conveniently extract the percent time between one new moon and the next 
    #This corresponds (somewhat roughly) to the phase of the moon. 

    #Use Year, Month, Day as arguments 
    date=ephem.Date(datetime.date(year,month,day)) 

    nnm = ephem.next_new_moon (date) 
    pnm = ephem.previous_new_moon(date) 

    lunation=(date-pnm)/(nnm-pnm) 

    #Note that there is a ephem.Moon().phase() command, but this returns the 
    #percentage of the moon which is illuminated. This is not really what we want. 

    return lunation 

def get_moons_in_year(year): 
    """Returns a list of the full and new moons in a year. The list contains tuples 
of either the form (DATE,'full') or the form (DATE,'new')""" 
    moons=[] 

    date=ephem.Date(datetime.date(year,01,01)) 
    while date.datetime().year==year: 
    date=ephem.next_full_moon(date) 
    moons.append((date,'full')) 

    date=ephem.Date(datetime.date(year,01,01)) 
    while date.datetime().year==year: 
    date=ephem.next_new_moon(date) 
    moons.append((date,'new')) 

    #Note that previous_first_quarter_moon() and previous_last_quarter_moon() 
    #are also methods 

    moons.sort(key=lambda x: x[0]) 

    return moons 

print get_phase_on_day(2013,1,1) 

print get_moons_in_year(2013) 

Esto devuelve

0.632652265318 

[(2013/1/11 19:43:37, 'new'), (2013/1/27 04:38:22, 'full'), (2013/2/10 07:20:06, 'new'), (2013/2/25 20:26:03, 'full'), (2013/3/11 19:51:00, 'new'), (2013/3/27 09:27:18, 'full'), (2013/4/10 09:35:17, 'new'), (2013/4/25 19:57:06, 'full'), (2013/5/10 00:28:22, 'new'), (2013/5/25 04:24:55, 'full'), (2013/6/8 15:56:19, 'new'), (2013/6/23 11:32:15, 'full'), (2013/7/8 07:14:16, 'new'), (2013/7/22 18:15:31, 'full'), (2013/8/6 21:50:40, 'new'), (2013/8/21 01:44:35, 'full'), (2013/9/5 11:36:07, 'new'), (2013/9/19 11:12:49, 'full'), (2013/10/5 00:34:31, 'new'), (2013/10/18 23:37:39, 'full'), (2013/11/3 12:49:57, 'new'), (2013/11/17 15:15:44, 'full'), (2013/12/3 00:22:22, 'new'), (2013/12/17 09:28:05, 'full'), (2014/1/1 11:14:10, 'new'), (2014/1/16 04:52:10, 'full')] 
1

PyEphem por defecto utiliza el tiempo universal coordinado (UTC). Quería un programa que generaría una lista de lunas llenas que sería precisa en la zona horaria del Pacífico. El siguiente código calculará las lunas llenas para un año determinado y luego ajustará eso usando el método ephem.localtime() para calibrar el huso horario deseado. También parece tener en cuenta adecuadamente el horario de verano también. Gracias a Richard, este código es similar a lo que él había escrito.

#!/usr/bin/python 
import datetime 
import ephem 
import os 
import time 

# Set time zone to pacific 
os.environ['TZ'] = 'US/Pacific' 
time.tzset() 

print("Time zone calibrated to", os.environ['TZ']) 

def get_full_moons_in_year(year): 
    """ 
    Generate a list of full moons for a given year calibrated to the local time zone 
    :param year: year to determine the list of full moons 
    :return: list of dates as strings in the format YYYY-mm-dd 
    """ 
    moons = [] 

    date = ephem.Date(datetime.date(year - 1, 12, 31)) 
    end_date = ephem.Date(datetime.date(year + 1, 1, 1)) 

    while date <= end_date: 
     date = ephem.next_full_moon(date) 

     # Convert the moon dates to the local time zone, add to list if moon date still falls in desired year 
     local_date = ephem.localtime(date) 
     if local_date.year == year: 
      # Append the date as a string to the list for easier comparison later 
      moons.append(local_date.strftime("%Y-%m-%d")) 

    return moons 

moons = get_full_moons_in_year(2015) 
print(moons) 

El código anterior devolverá:

Time zone calibrated to US/Pacific 
['2015-01-04', '2015-02-03', '2015-03-05', '2015-04-04', '2015-05-03', '2015-06-02', '2015-07-01', '2015-07-31', '2015-08-29', '2015-09-27', '2015-10-27', '2015-11-25', '2015-12-25']