programing

달/달 위상 알고리즘

jooyons 2023. 7. 9. 11:05
반응형

달/달 위상 알고리즘

주어진 날짜에 달의 위상이나 나이를 계산하거나, 주어진 해의 새로운/보름달의 날짜를 찾는 알고리즘을 아는 사람이 있습니까?

구글링은 제게 해답이 천문학 책에 있다고 말하지만, 한 페이지만 필요할 때는 책 전체를 사고 싶지 않습니다.

업데이트:

저는 구글링에 대한 제 진술을 조금 더 잘 검증했어야 했습니다.저는 (1900년대처럼) 일부 시간 동안만 작동하는 솔루션과 제가 원하는 것보다 더 비싼 계산 비용이 드는 트리그 기반 솔루션을 찾았습니다.

그의 파이썬 책에 있는 S Lott는 주어진 해의 부활절을 계산하기 위한 몇 가지 알고리즘을 가지고 있는데, 대부분은 10줄 미만의 코드이고 일부는 그레고리력의 모든 날에 대해 작동합니다.3월에 보름달을 찾는 것은 부활절을 찾는 데 중요한 요소이기 때문에 그레고리력의 모든 날짜에 대해 트리거와 작동을 필요로 하지 않는 알고리즘이 있어야 한다고 생각했습니다.

만약 당신이 나와 같다면, 당신은 신중한 프로그래머가 되려고 노력합니다.그래서 복잡한 천문학적인 문제를 해결하기 위한 것이라고 주장하지만 해결책이 왜 옳은지 설명하지 못하는 무작위 코드가 인터넷에 흩어져 있는 것을 보면 긴장하게 됩니다.

당신은 신중하고 완전한 해결책을 포함하는 책과 같은 권위 있는 출처가 있어야 한다고 믿습니다.예를 들어:

미어스, 진.천문학 알고리즘.Richmond: Willmann-Bell, 1991. ISBN 0-943396-35-2.

더핏 스미스, 피터계산기를 사용한 실용적인 천문학.3단.케임브리지:케임브리지 대학 출판부, 1981. ISBN 0-521-28411-2.

정적 웹 페이지와 달리 오류를 수정할 수 있는 널리 사용되고 테스트를 거친 오픈 소스 라이브러리를 신뢰할 수 있습니다.그렇다면, Phases of the Moon 인터페이스를 사용하여 PyEphem 라이브러리를 기반으로 한 질문에 대한 파이썬 솔루션입니다.

#!/usr/bin/python
import datetime
import ephem
from typing import List, Tuple

def get_phase_on_day(year: int, month: int, day: int):
  """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: int) -> List[Tuple[ephem.Date, str]]:
  """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,1,1))
  while date.datetime().year==year:
    date=ephem.next_full_moon(date)
    moons.append( (date,'full') )

  date=ephem.Date(datetime.date(year,1,1))
  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')]

나는 얼마 전에 이것을 위해 Python에 코드를 이식했습니다.그냥 링크만 하려고 했는데, 알고 보니 웹에서 떨어져서 먼지를 털어내고 다시 업로드해야 했습니다.John Walker의 도구에서 파생 moon.py 을 참조하십시오.

저는 이것에 대한 참고 자료를 찾을 수 없지만, 저자들이 꽤 엄격했던 것 같습니다.그 말은, 네, 그것은 trig를 사용한다는 것을 의미합니다. 하지만 저는 당신이 이것을 계산적으로 금지하는 데에 무엇을 사용할지 상상할 수 없습니다.Python 함수 호출 오버헤드는 아마도 trig 연산의 비용 이상일 것입니다.컴퓨터는 계산 속도가 꽤 빠릅니다.

코드에 사용되는 알고리즘은 다음 소스에서 추출됩니다.

미어스, 진.천문학 알고리즘.Richmond: Willmann-Bell, 1991. ISBN 0-943396-35-2.

꼭 필요한 책입니다. 한 권만 사신다면, 꼭 이것이 맞는지 확인하세요.알고리즘은 컴퓨터 프로그램이 아닌 수학적으로 제시되지만, 책에 있는 많은 알고리즘을 구현하는 소스 코드는 QuickBasic, Turbo Pascal 또는 C에서 출판사와 별도로 주문할 수 있습니다.Meeus는 코드를 디버깅하는 데 필수적인 계산의 많은 작업된 예를 제공하고 정확성, 속도, 복잡성 및 장기(세기 및 천년) 유효성 사이에서 서로 다른 트레이드오프를 가진 여러 알고리듬을 자주 제시합니다.

더핏 스미스, 피터계산기를 사용한 실용적인 천문학.3단.케임브리지:케임브리지 대학 출판부, 1981. ISBN 0-521-28411-2.

제목에 계산기라는 단어가 있음에도 불구하고 행성의 위치, 궤도, 일식 등을 계산하는 소프트웨어를 개발하는 데 관심이 있다면 유용한 참고 자료입니다.Meeus보다 더 많은 배경 정보가 제공되며, 이는 천문학에 아직 익숙하지 않은 사람들이 자주 혼동되는 용어를 배우는 데 도움이 됩니다.주어진 알고리즘은 Meeus가 제공하는 알고리즘보다 간단하고 정확도가 낮지만 대부분의 실제 작업에 적합합니다.

당신이 구글을 잘못 검색한 것 같습니다.

또한 Pyephem - 파이썬 패키지이지만 C에 계산 내장이 있는 과학적 수준의 천문학 루틴 [PyPI], 그리고 그것은 다음과 같습니다.

-1369 ~ +2950 범위의 정밀도 < 0.05"입니다.
테이블 조회 기술을 사용하여 삼각 함수에 대한 호출을 제한합니다.

PyEmphem은 이제 더 이상 사용하지 않습니다. 그들은 새로운 프로젝트를 위해 PyEmphem보다 Skyfield 천문학 라이브러리를 선호할 것을 권장합니다.그것의 현대적인 디자인은 더 나은 파이썬 코드를 장려하고 계산을 가속화하기 위해 NumPy를 사용합니다.

달의 위상은 황도를 따라 달과 태양 사이의 각도로 정의됩니다.이 각도는 달과 태양의 황경도 차이로 계산됩니다.

결과는 초승달의 경우 0°, 번째 분기의 경우 90°, 보름달의 경우 180°, 마지막 분기의 경우 270°의 각도입니다.

여기서 가져온 코드

from skyfield.api import load
from skyfield.framelib import ecliptic_frame

ts = load.timescale()
t = ts.utc(2019, 12, 9, 15, 36)

eph = load('de421.bsp')
sun, moon, earth = eph['sun'], eph['moon'], eph['earth']

e = earth.at(t)
_, slon, _ = e.observe(sun).apparent().frame_latlon(ecliptic_frame)
_, mlon, _ = e.observe(moon).apparent().frame_latlon(ecliptic_frame)
phase = (mlon.degrees - slon.degrees) % 360.0

print('{0:.1f}'.format(phase))

산출량

149.4

Pyephem은 기본적으로 UTC(Coordinated Universal) 시간을 사용합니다.저는 태평양 시간대에 정확한 보름달 목록을 생성할 수 있는 프로그램을 원했습니다.아래 코드는 특정 연도의 보름달을 계산한 다음 ephem.localtime() 방법을 사용하여 원하는 시간대로 보정합니다.또한 일광 절약 시간도 적절하게 고려하는 것으로 보입니다.리차드에게 감사합니다, 이 코드는 그가 작성한 것과 비슷합니다.

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

위의 코드가 반환됩니다.

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

Python을 찾고 있는 것은 알지만 C#을 이해할 수 있다면 Chronos XP라는 오픈 소스 프로젝트가 있으며 이를 매우 잘 수행합니다.

높은 정확도가 필요하지 않은 경우 언제든지 (ab) 음력(또는 음력) 달력 클래스(예:HijriCalendar또는ChineseLunisolarCalendarMicrosoft .NET의 경우 달력의 "달의 일" 속성으로서 항상 달의 위상(예: 1일은 초승달, 15일은 보름달 등)을 계산합니다.

언급URL : https://stackoverflow.com/questions/2526815/moon-lunar-phase-algorithm

반응형