月球/月相算法

Sco*_*ley 34 c python algorithm calendar astronomy

有没有人知道一个算法,要么计算给定日期的月相或年龄,要么找到给定年份新月/满月的日期?

谷歌搜索告诉我答案是在一些天文学书籍中,但当我只需要一页时,我真的不想买整本书.

更新:

我应该证明我对google搜索更好一点的说法.我确实找到了只在某个时间段内工作的解决方案(如1900年代); 以及基于触发器的解决方案,其计算成本将超出我的预期.

S Lott在他的Python书中有几种算法用于计算给定年份的复活节,大多数算法少于十行代码,有些算法适用于格里高利历中的所有日子.在3月份找到满月是寻找复活节的关键因素,所以我认为应该有一个不需要触发的算法,适用于格里高利历中的所有日期.

ket*_*urn 17

我暂时将一些代码移植到Python.我本来只是链接到它,但事实证明它在此期间从网上掉了下来,所以我不得不去掉它并再次上传它.见moon.py它源自约翰·沃克的moontool.

我无法找到这方面的参考资料,因为时间跨度也是准确的,但似乎作者非常严谨.这意味着是的,它确实使用了trig,但是我无法想象你将使用它会是什么,这将使它在计算上受到限制.Python函数调用开销可能超过了trig操作的成本.计算机的计算速度非常快.

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

迈耶斯,让.天文算法.Richmond:Willmann-Bell,1991.ISBN 0-943396-35-2.

必备; 如果你只买一本书,请确保它是这本书.算法以数学方式呈现,而不是计算机程序,但实现本书中许多算法的源代码可以与QuickBasic,Turbo Pascal或C中的发布者分开订购.Meeus提供了许多有用的调试计算示例您的代码,并经常提出几种算法,在准确性,速度,复杂性和长期(世纪和千年)有效性之间进行不同的权衡.

达弗特 - 史密斯,彼得.实用的天文学与您的计算器.第3版.剑桥:剑桥大学出版社,1981.国际标准书号0-521-28411-2.

尽管标题中有计算器这个词; 如果您对开发计算行星位置,轨道,日食等的软件感兴趣,这是一个有价值的参考.提供了比Meeus更多的背景信息,这有助于那些不熟悉天文学的人学习常常令人困惑的术语.给出的算法比Meeus提供的算法更简单,更准确,但适用于大多数实际工作.

  • "计算机的计算速度非常快." - 我喜欢它!我可能不得不引用那个. (15认同)

Ric*_*ard 12

如果你像我一样,你会成为一个细心的程序员.因此,当您看到分散在互联网上的随机代码旨在解决复杂的天文问题时会让您感到紧张,但却无法解释为什么解决方案是正确的.

您认为必须有权威的来源,例如包含细致且完整的解决方案的书籍.例如:

迈耶斯,让.天文算法.Richmond:Willmann-Bell,1991.ISBN 0-943396-35-2.

达弗特 - 史密斯,彼得.实用的天文学与您的计算器.第3版.剑桥:剑桥大学出版社,1981.国际标准书号0-521-28411-2.

您可以信赖广泛使用且经过良好测试的开源库,这些库可以纠正错误(与静态网页不同).在这里,是一个基于PyEphem库的问题的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)
Run Code Online (Sandbox Code Playgroud)

这回来了

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')]
Run Code Online (Sandbox Code Playgroud)


Jac*_*ack 11

我认为你搜索错误的谷歌:

  • -1 StackOverflow的一个很好的功能是人们可以来这里寻求答案,而不是链接到答案.此外,您的顶部链接已损坏,您的第二个链接没有引用说服一个细心的程序员,其中列出的算法是正确的,您的第三个链接有引用,但代码已全部从原件更改.第四个环节同样存在问题. (5认同)
  • @Jack:哇!+1 ......记忆.我不知道我从哪里知道这个名字:"Ben Daglish".他是当时C64上8位音乐作曲家中最好的(我说*一个*;)作曲家之一.很高兴找到一个与他完全无关的链接(我不得不通过他的网站搜索,直到我发现C64链接记住我知道这个名字的地方). (2认同)
  • 谁的谷歌?对于不同的人来说,点击率确实不同。 (2认同)

ket*_*urn 7

此外,pyephem - 科学级天文学例程 [ PyPI ],这是一个Python包,但在C中具有计算胆量,并且确实

从-1369到+2950的精度<0.05".
使用表查找技术来限制对三角函数的调用.


Gal*_*cha 7

PyEphem现已弃用 - 对于新项目,他们建议优先使用Skyfield 天文学库而不是 PyEphem。其现代设计鼓励更好的 Python 代码,并使用 NumPy 来加速其计算。

\n
\n

月相被定义为月球和太阳之间沿黄道的角度。该角度根据月球和太阳的黄道经度之差计算。

\n
\n

结果是新月的角度为 0\xc2\xb0,上弦月的角度为 90\xc2\xb0,满月的角度为 180\xc2\xb0,下弦月的角度为 270\xc2\xb0

\n

代码取自这里

\n
from skyfield.api import load\nfrom skyfield.framelib import ecliptic_frame\n\nts = load.timescale()\nt = ts.utc(2019, 12, 9, 15, 36)\n\neph = load(\'de421.bsp\')\nsun, moon, earth = eph[\'sun\'], eph[\'moon\'], eph[\'earth\']\n\ne = earth.at(t)\n_, slon, _ = e.observe(sun).apparent().frame_latlon(ecliptic_frame)\n_, mlon, _ = e.observe(moon).apparent().frame_latlon(ecliptic_frame)\nphase = (mlon.degrees - slon.degrees) % 360.0\n\nprint(\'{0:.1f}\'.format(phase))\n
Run Code Online (Sandbox Code Playgroud)\n

输出

\n
149.4\n
Run Code Online (Sandbox Code Playgroud)\n