浮点精度问题的处理

计算时发现转换为JD值时,如2000年1月1日0点0时0分,JD值为2451545.4166707597,在还原时,变成了1999年12月31日23点59分59.999986588954926秒,这是因为浮点计算的问题导致。 通过人工修正加入一秒1/86400后,秒数变成了0.999981164932251111,换而言之,这里稳定的浮点数是0.99998这里,由于1000毫秒为1秒,而天象计算也不可能精确到这种程度,所以这里的计算可以进行简化。 故需进行浮点修正: var xxx = Math.Round(v - Math.Floor(v), 6); if (xxx < 0.50001) {         jd = v - xxx - 0.5 + 0.00001; } if (xxx > 0.50001)…

Read More

1903年为什么是闰五月?谈农历中气与合朔同日的闰月情况

编写的代码中,发现日历上,1903闰五月,然而计算出来的却不是,结过一番仔细排查,发现原因所在。 1903年7月24日9点交大暑节,然而日月合朔却是在7月24号晚上20点,如果按严格的时间来说,此处大暑节属于上一节之中,故上一节中不应该进行置闰月。 然而按农历的历法规定并没有精确到时辰,而是认为7月24号有合朔,所以7月24号子时开始,就已经是初一了,这个类似于超接。 然后大暑节虽然提早到来,然而在历法中,归属在此月节中,所以此年是闰五月。 在编码中,则需要考虑到这个问题:如果本月的中气与下一月初一在同一天,那么本月要当作没有中气,进行置闰处理。

Read More

弦截法计算日月合朔

设时刻T还有T',并设T'=T,再设一个t 1、计算T时刻太阳黄经 2、计算T+t太阳黄经 3、计算T-t太阳黄经 4、计算T时刻月球黄经 5、计算T+t月球黄经 6、计算T-t月球典经 7、求T时刻太阳黄经与月球黄经之差 8、T+t的时刻的月亮黄经 减去 T-t时刻的月球黄经 加上 T- t时刻的太阳黄经 送去 T+t时刻的太阳黄经 ,再除以1e-6 9、第7步结果除以第8步结果,再用T减去这个结果,得到 T' 10、判断T'与T的差值绝对值,是否达到精度要求,如果未达到,则设T=T',然后从头开始再算。 如此T会不断更新为新的计算结果,然后不断精度越来越高,通常达到一分钟以下的精度即可,而且即使是一分钟的精度,也会与现实有所误差,所以这种计算也只是一个模拟值。  

Read More

SwissEphNet

为了尝试能够实现Windows上开发,Linux上运行,所以采用了Asp.net core,然而在使用SwissEphNet时,发现一个重大的问题,SwissEphNet读文件是调用一个事件,然后在这个事件用返回一个文件流,然后在这个文件流又返回给一个包装的CFile,然后CFile又返回给一另外的对象,更糟糕的是它层层迭代后,弄得一片混乱,有地方没有对流进行Dispose,因为没有释放资源就导致了在多线程访问时,会提示文件已经被其它进程占用。   因为其调用代码简直是满目疮痍,混乱一片,无法从内部进行修改,所以就采用了取巧的方法解决,每次创建一个CFILE对象时,就将它注册到一个字典里,并将当前的流记录下来,遇到再次访问相同文件时,就去反查该文件的流,并进行Dispose释放,然后重新创建CFile对象,如此暂时解决了问题。 推测应该是内存回收管理机制的问题,因为包装引用太多,虽然在代码中进行Dispose了,但仍然有地方可能有牵扯不清的引用,导致它不能指针变空,结果就导致了流无法翻译。

Read More

寿星万年历中的精度问题

寿星万年历的精度很准了,然而它的日月交朔时间,在计算2016年7月4号时,其交朔为北京时间19:00:56。通过计算发现,这里的精度值稍有此许问题,因为理论上1天有24*60分钟,计算出来约0.6744e-4代表一分钟,所以在采用的粒度选值也在这个范围,在寿星万年历中采用的是快速截弦法,计算速度极快,然而如果采用更精密的数据时,可以将粒度调整为更细,此时会发现实际上更精确的时间应该交朔时间应该是北京时间18:59:59.89秒,这与2016年的朔望弦交蚀时刻表是一致的。如果要追根究底的话,这个时间点非常重要,因为在19点以前仍然是酉时,19点以后已经是戌时,但同时考虑到天文的误差,虽然计算上认为可以精确到分钟,然而实际天象能够有如此精确,很难说得清的,所以寿星万年历还是非常精确的。

Read More