标题: 51单片机可否实现上下五千年农历计算(非查表法) [打印本页]

作者: exv    时间: 2014-12-6 11:39
标题: 51单片机可否实现上下五千年农历计算(非查表法)
本帖最后由 exv 于 2014-12-6 12:58 编辑

看了论坛中几个有农历的时钟程序,无一例外使用查表法实现的,且只能查上下100年(因为DS1302只有上下一百年)。

看过莆田第十中学许剑伟老师的农历算法,可实现上下五千年农历的计算(含节气),
与主函数直接相关的C代码就有6000余行;
关于日月星辰轨道计算的代码有数十组,
每一组换算往往涉及几十个64位double。

不知道51单片机在 合理 配置的情况下,能否实现这样的计算?

如果不行,实现这一功能的最低配置是?

许剑伟老师的代码这儿就不贴了(估计也贴不下),百度下 莆田第十中学许剑伟老师 即可。

51hei人才济济,下面这段计算圆周率的代码大家应该非常熟悉,古人几十本书还没说清的一两行就搞定了:
  1. long a=10000,b,c=2800,d,e,f[2801],g;
  2. void main(){for(;b-c;)f[b++]=a/5;for(;d=0,g=c*2;c-=14,cout<<e+d/a,e=d%a)for(b=c;d+=f[b]*a,f[b]=d%--g,d/=g--,--b;d*=b);}
复制代码


古人制农历最多也就是算盘,难道 51单片机 真敌不过古人算盘?

另外,许老师的日历程序除了可定农历日期/节气,还可依此结合设定的经纬度换算出每天的日落日出,非常实用。


作者: dgahz    时间: 2014-12-6 12:25
不会,太高深了。算盘结果可暂记纸上,记多少都可以,容量无限大,今天记不完明天接着记,速度可以无限慢。如果比这些,51单片机还真拍马莫及。
作者: exv    时间: 2014-12-6 12:45
dgahz 发表于 2014-12-6 12:25
不会,太高深了。算盘结果可暂记纸上,记多少都可以,容量无限大,今天记不完明天接着记,速度可以无限慢。 ...

程序本身并不高深,有高中水平即能看懂(不然 莆田第十中学的学生们可就悲催了),也就是些牛顿方程什么的。

只是这么大的计算量,放在RAM有限的51单片机确实是一个麻烦,也难怪目前能见到的都是查表法实现的。

不知如果借助一个2M的EEPROM能否解决这个问题?
作者: dgahz    时间: 2014-12-6 13:40
农历是怎么算出来的我真搞不懂,和牛顿有关?印象中牛顿是力学吨
作者: dgahz    时间: 2014-12-6 13:41
出社会太久,知识都丢了。
作者: 风缘    时间: 2014-12-6 16:31
应该是不管用吧
作者: exv    时间: 2014-12-6 16:40
本帖最后由 exv 于 2014-12-6 16:46 编辑

还是贴一些莆田十中许老师的代码给大家温习下相关知识:

1.算出太阳/月亮/地球的位置(牛顿力学)
2.反算太阳月亮视黄经,相等时刻定月初一
3.根据各个月初一导出整个农历,节气可从太阳黄经直接导出。

许老师的代码虽然多,有相当部分是固定不变的天文/地理参数,包括一大堆校正因子集,故而前面的帖子提出使用EEPROM作存储辅助。

既然圆周率求算都能从几十本书变为两行代码,农历又是极为常用的东西,必定有非常多人去研究,一个简洁高效能在单片机上运行的代码应该是已经有人写出过的。

下面代码是通过地球轨道方程反算太阳黄经,从而计算出各个节气。
(51hei只见到一个历法程序有节气,只是人家没给代码,不知道是不是用下面方法算出的)


  1. double qi_low(double W)
  2. {
  3.         //最大误差小于30分钟,平均5分
  4.         double t,L,v= 628.3319653318;
  5.         t =  ( W - 4.895062166 )/v; //第一次估算,误差2天以内
  6.         t -= ( 53*t*t + 334116*cos( 4.67+628.307585*t) + 2061*cos( 2.678+628.3076*t)*t )/v/10000000; //第二次估算,误差2小时以内
  7.         
  8.         L = 48950621.66 + 6283319653.318*t + 53*t*t //平黄经
  9.                 +334166 * cos( 4.669257+  628.307585*t) //地球椭圆轨道级数展开
  10.                 +3489 * cos( 4.6261  + 1256.61517*t ) //地球椭圆轨道级数展开
  11.                 +2060.6 * cos( 2.67823 +  628.307585*t ) * t  //一次泊松项
  12.                 - 994 - 834*sin(2.1824-33.75705*t); //光行差与章动修正
  13.         
  14.         t -= (L/10000000 -W )/628.332 + (32*(t+1.8)*(t+1.8)-20)/86400/36525;
  15.         return t*36525 + (double)8/24;
  16. }
复制代码



作者: a719563181    时间: 2015-3-20 11:26
好高深的有没有?反正我是看迷糊了
作者: exv    时间: 2015-3-20 17:48
a719563181 发表于 2015-3-20 11:26
好高深的有没有?反正我是看迷糊了

其实,是有的问题被复杂化了。

农历本来是用来指导一年的农时,大多数时候也不需要精确到分秒。
如同买鞋子的时候最多用皮尺之类的工具量量尺寸,没人会去用游标卡尺。

这一步
1.算出太阳/月亮/地球的位置(牛顿力学)

为了得到精确的值,使用近代天文学算法(多体),耗费了大量计算资源。
现代算法是从《史记历书》演化而来,只是司马迁直接把太阳月亮假设为匀速圆周运动,通过这样一个近似,计算量极大减小,所得的历法也满足指导农时之用。

当然,现代算法也是一种学问上的严谨。日月食的时间能精确到秒(参看许老师代码)。
作者: zw_mcu    时间: 2017-5-11 11:01
很好的资料




欢迎光临 (http://www.51hei.com/bbs/) Powered by Discuz! X3.1