月亮/月相算法

问题描述 投票:34回答:9

没有人知道一种算法来计算给定日期的月相或年龄,或者找到给定年份中新月/满月的日期吗?

Google告诉我答案是在一本天文学书籍中,但是当我只需要一页时,我真的不想买整本书。

更新:

我应该对有关谷歌搜索的陈述有所保留。我确实找到了只能在某些时间范围内工作的解决方案(例如1900年代);以及基于trig的解决方案,这些解决方案在计算上会比我想要的昂贵。

S Lott在他的Python书中有几种算法来计算给定年份的复活节,大多数算法少于十行代码,并且在公历中的某些日子都可以工作。查找三月的满月是查找复活节的关键部分,因此我认为应该有一种算法,该算法不需要触发就可以用于公历中的所有日期。

python c algorithm calendar astronomy
9个回答
18
投票

前一段时间,我将一些代码移植到了Python。我本来只是要链接到它,但是事实证明它是同时从网络上掉下来的,所以我不得不清除它并重新上传它。请参见从moon.py派生的John Walker's moontool

我在这两个时间段内都找不到准确的参考,但作者似乎非常严格。这意味着是的,它确实使用了trig,但是我无法想象您将为此使用的到底将使它在计算上变得令人望而却步。 Python函数调用的开销可能比trig操作的开销更大。计算机的计算速度非常快。

代码中使用的算法来自以下来源:

Meeus,Jean。天文算法。列治文:威尔曼·贝尔(Willmann-Bell),1991年。ISBN0-943396-35-2。

必备品;如果您只买一本书,请确保它是这本书。算法以数学方式而不是计算机程序形式呈现,但是可以使用QuickBasic,Turbo Pascal或C从出版商处单独订购实现本书中许多算法的源代码。Meeus提供了许多对调试必不可少的计算示例您的代码,并经常在精度,速度,复杂性和长期(世纪和千年)有效性之间提出几种折衷的算法。

Duffett-Smith,彼得。您的计算器的实用天文学。第三版。剑桥:剑桥大学出版社,1981年。ISBN0-521-28411-2。

尽管标题中有计算器一词;如果您对开发计算行星位置,轨道,日食等的软件感兴趣,那么这是一个有价值的参考。比Meeus提供的背景信息更多,这可以帮助那些尚未精通天文学的人学习经常混淆的术语。与Meeus提供的算法相比,给出的算法更简单,准确性更低,但适用于大多数实际工作。


13
投票

如果您像我一样,请尝试成为一名谨慎的程序员。因此,当您看到散布在互联网上的随机代码声称可以解决复杂的天文问题,但却无法解释该解决方案为何正确时,您会感到不安。

您认为必须有权威的资源,例如books>],其中包含仔细而完整的解决方案。例如:

Meeus,Jean。天文算法。列治文:Willmann-Bell,1991年。ISBN0-943396-35-2。

达菲特·史密斯,彼得。您的计算器的实用天文学。第三版。剑桥:剑桥大学出版社,1981年。ISBN0-521-28411-2。

您将信任放在使用广泛,经过良好测试的开放源代码库中,这些库可以纠正其错误(与静态网页不同)。然后,这里是使用PyEphem接口基于Phases of the Moon库针对您的问题的Python解决方案。

#!/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)

此返回

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')]

11
投票

我认为您在错误的Google上搜索:


7
投票

pyephem — scientific-grade astronomy routines [PyPI],这是一个Python程序包,但具有computational guts in C,并且does


3
投票

Pyephem默认情况下使用协调世界时(UTC)时间。我想要一个程序,该程序可以生成在太平洋时区准确的满月列表。下面的代码将计算给定年份的满月,然后使用ephem.localtime()方法对其进行调整以校准到所需的时区。它还似乎也可以正确考虑夏令时。谢谢Richard,此代码类似于他编写的代码。


0
投票

[我知道您正在寻找Python,但是如果您能理解C#,那么就有一个名为Chronos XP的开源项目,它做得很好。


0
投票

[如果不需要高精度,则始终可以(ab)使用农历(或阴阳)日历类(例如Microsoft .NET中的HijriCalendarChineseLunisolarCalendar)来计算(近似)月相任何日期,作为日历的“月日”属性,是农历(或阴阳)日历日,总是对应于月相


0
投票

在不知道该阶段确切的农历日是什么时候,此计算不是很有用。有人也可以添加农历日的计算吗?


-1
投票

一个快速的Google透露了this

© www.soinside.com 2019 - 2024. All rights reserved.