搜索
bottom↓
回复: 3

AVR里边计算天数差的法子

[复制链接]

出0入0汤圆

发表于 2012-11-28 23:30:12 | 显示全部楼层 |阅读模式
打算计算天数差,翻了翻网上的讨论,都用了循环。可是像M8这样的芯片,RAM倒是有几个,可速度就不是很快。用循环在PC上也许更合适。

想了想,反正每400年公历就经历一个循环,找出400年内的润平年数,就能用乘加的方法一次性算出相对某个400年周期的总天数,然后天数差就好算了。

从表中看出,公元0年、400年...2000年是闰年(当然历法中没规定0年),所以起始加一,然后再屏蔽掉一个闰年就能得到400年内的全部闰年数,再用年数乘365之后就得到本年之前经过的总天数了。之后确定本年内的天数,就得到包括当前日期在内的全部天数。这样就回避了循环。

用OCTAVE验证之后写了下面的程序。还附了一个计算annual date的程序,两个加起来比较好用。

程序里叫做qdt_time_t的类型不过是包含年月日整型变量的一个结构而已。
  1. /*
  2.         The days of the past years can be calculated by using the following formula:
  3.         The year:        2000        2001        2002        2003        2004        2005        2006        2007        2008        2009        2010        2011        2012
  4.         MOD 400:        0                1                2                3                4                5                6                7                8                9                10                11                12
  5.         Leap year:        0                1                0                0                0                1                0                0                0                1                0                0                0
  6.         Days past:        0                366                365                365                365                366                365                365                365                366                365                365                365
  7.         The sums:        0                366                731                1096        1461        1827        2192        2557        2922        3288        3653        4018        4383

  8.         Formula:        n = 1 + y*365 + fix((y-1)/4) - fix((y-1)/100) + fix((y-1)/400)
  9.        
  10.         Before 2012, we have 4383 + 146097 * 5 = 734868 days past. Where 146097 = 365 * 400 + 97 is a 400 years cycle.
  11. */
  12. uint32_t qdt_to_long_date(const qdt_time_t *time)
  13. {
  14.         uint16_t year = time->year;

  15.     /* The DOY means what day is today of the year. It is an annual date. */
  16.     uint32_t days;
  17.        
  18.         if(year == 0){
  19.                 days = 0;
  20.         }else{
  21.                 days = 1 + year * 365UL;
  22.                 year --;
  23.                 days += year/4 - year/100 + year/400;
  24.         }

  25.         /* Add the annual date at the final. */
  26.         days += qdt_day_of_annual(time);

  27.         return days;
  28. }
复制代码
  1. uint16_t qdt_day_of_annual(const qdt_time_t *time)
  2. {
  3.         /* Days accumulation table of an ordinary year. */
  4.         static const uint16_t PROGMEM annual_table[] = {
  5.         /*  x  1   2   3   4    5    6    7    8    9   10   11   12 */
  6.             0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334
  7.         };

  8.         /* Use buffered values. */
  9.         uint8_t month = time->month;
  10.         uint8_t day = time->day;
  11.        
  12.     /* Using 16-bit unsigned integer accumulator. */
  13.     uint16_t days = day + pgm_read_word(&annual_table[month]);

  14.     /* Append one day in leap year. */
  15.     if((month > 2) && qdt_is_leap_year(time)){
  16.         days += 1;
  17.     }

  18.     return days;
  19. }
复制代码
  1. uint8_t qdt_is_leap_year(const qdt_time_t *time)
  2. {
  3.         /* For every 400 years, it's transmigrated. */
  4.         uint16_t year = time->year % 400;
  5.        
  6.         return ((year == 0) || ((year % 4 == 0) && (year % 100 != 0)));
  7. }       
复制代码

阿莫论坛20周年了!感谢大家的支持与爱护!!

知道什么是神吗?其实神本来也是人,只不过神做了人做不到的事情 所以才成了神。 (头文字D, 杜汶泽)

出0入0汤圆

 楼主| 发表于 2012-11-28 23:32:24 | 显示全部楼层
啊呀格式好乱,凑合看吧。

出0入0汤圆

 楼主| 发表于 2012-11-28 23:44:14 | 显示全部楼层
又试了试,还能计算星期数:
  1. uint8_t qdt_day_of_week(const qdt_time_t *time)
  2. {
  3.         uint32_t days;

  4.         /* Calculate the days with the Saturday compensation. */       
  5.         days = (qdt_to_long_date(time) - 1) + 6;
  6.        
  7.         return days % 7;
  8. }       
复制代码
初验好像对的,有错误就以后更正。

出0入0汤圆

发表于 2014-3-6 23:13:36 | 显示全部楼层
擦,高手的帖子,顶一下,这算是科研了,一般人还真不知道为何要琢磨这个
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片。注意:要连续压缩2次才能满足要求!!】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-7-24 00:17

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表