3

关于《算法的乐趣》历法一章演示程序错误的说明

 3 years ago
source link: https://blog.csdn.net/orbit/article/details/51138705
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

关于《算法的乐趣》历法一章演示程序错误的说明

original.png
吹泡泡的小猫 2016-04-13 00:37:13 6632
¥99.00

最近有网友在微博上向我反映,《算法的乐趣》随书的例子代码中关于农历历法的演示程序出了BUG,并截了图给我,我开始以为是算法中的某些部分不兼容64位系统,后来发现在32位系统上一样有问题,什么问题呢?先看看截图:

这里写图片描述

看到了吧,“三十月大”,走查代码,发现是处理农历闰月的时候重拍月序关系,导致越界访问了。对了一下历法,2015年不是闰年,怎么会走到闰月处理的流程中去了呢?
跟了一下代码,终于找到原因了,原来是“民间历法”和“历理历法”的差异捣的鬼。先复习一下《 算法系列之二十:计算中国农历(二) 》中关于“民间历法”和“历理历法”的小知识:

新中国成立以后没有颁布新的“官方农历历法”,将历法和政治分离体现了时代的进步,但是由于没有 “官方历法”,也引起了一些问题。比如我国现在采用的农历历法是《时宪历》,它源于清朝顺治年间(公元1645)颁布的《顺治历》,它有两个不足之处:一个是日月合朔和节气的时间以北京当地时间为准,也就是东经116度25分的当地时间,其节气和新月的观察只适用于中原地区。其它经度的地方,因为时间的关系,对导致日月合朔和节气时间的差异导致置闰和月顺序各不相同。另一个不足之处就是日月合朔时间和节气时间判断不精确,如果日月合朔时间和节气时间在同一天,不管具体的时间是否有先后,一律将此节气算做新月中的节气,这样一来,如果这个节气是中气,就会影响到闰月的设置。历理历法针对这两点进行了改进,对节气时间和日月合朔时间统一采用东经120度即东八区标准时,这样在任何时区的节气和置闰结果都是一样的,以东八区标准时为准。对于节气时间和日月合朔时间在同一天的情况,精确计算到时、分、秒,只有日月合朔时间在节气时间之前,这个节气才包含在次月内。历理历法从理论上讲更符合现代天文学的精确计算,但是需要注意的是,历理历法仍然只是存在于理论上的历法,我国现行的农历历法依然是民间历法《时宪历》或《顺治历》。

对比一下计算得到的儒略日,2014年的冬至节气是2014年12月22日 07时02分,2014年农历冬月(十一月)初一刚好也是这一天,具体时间是2014年12月22日 09时35分。如果严格按照历理历法,这个冬月的朔日应该算在2015年农历年中,也就是说,2015年应该是闰年(2015年冬至是2015年12月22日12时47分,两个冬至节气之间有13个朔日)。但是实际历法是2014年是闰年,因为我们目前仍然采用的是民间历法,当节气和朔日在同一天时,不管实际的先后顺序,一律将此节气算作此农历月的中气,实际上就把这个农历月划到了2014年,这样以来,2014年就多了一个朔望月,自然就在2014年置闰了,2015年就不应该是闰年了。
随书给出的算法简单地按照历理历法计算闰年,将2014年12月22日 09时35分这个新月算作2015年,刚好这个月没有中气(冬至就是中气,但是因为早了2个小时,就被算作上个月的节气了),于是就按照规则置闰,于是就越界了。
知道问题原因了,解决方法就简单了。要么仍然按照历理历法处理,只需要解决置闰算法部分的异常,解决越界问题就行了。要么按照民间历法来,当冬至和朔日是同一天时,无论实际的时间先后,都将冬至节气算作这个月的中气。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK