程序员的算法趣题--入门篇(c++描述)日期的二进制转换

问题描述:

  把年月日表示为 YYYYMMDD 这样的 8 位整数,然后把这个整数转换成 二进制数并且逆序排列,再把得到的二进制数转换成十进制数,求与原日期一 致的日期。求得的日期要在上一次东京奥运会(1964 年 10 月 10 日)到下一 次东京奥运会(预定举办日期为 2020 年 7 月 24 日)之间。

例)日期为1966年7月13日时 ① YYYYMMDD格式→ 19660713 ② 转换成二进制数→ 1001010111111111110101001 ③ 逆序排列→ 1001010111111111110101001 ④ 把逆序排列得到的二进制数转换成十进制数→ 19660713

分析:

  处理日期多麻烦哦,我们交给库函数处理,嘿嘿。剩下的我们需要考虑怎样优化算法。先看时间转化为二进制的范围196410101001010111111111110101001‬,20200724→‭1001101000011110100010100‬。可以看到二进制前4位是一样的,所以后面的四位也需要是1001。即我们所需要的十进制数字满足:(dec - 9 )%16 == 0 -----(1),这里我们需要分两种情况考虑:

  • 当前日期加上16时年月不变,这时我们可以直接用之前的日期十进制数加上16作为下个十进制数,而不需要再次转化。
  • 当前日期加上16年或月变化,这时我们需要将当前的日期日期重置1,重新寻找满足等式(1)的十进制数字。

代码实现:

#include <time.h>
#include <vector>
using std::vector;
int toDec (const tm & cur_date);
void getNext (tm* cur_date);
void searchStart(int encoded, tm* start_date);
int main() {
    struct tm start_date = {0};
    vector <tm> res;
    start_date.tm_mday = 1;start_date.tm_year = 70;start_date.tm_mon = 0;//mktime is available after 1970.
    int encoded = toDec(start_date);
    searchStart(encoded, &start_date);
    while (encoded <= 20200724){
        int p_end = 0x00000010, p_begin = 0x00100000;
        while (p_end != p_begin){
            if ((bool)(p_begin & encoded) == (bool)(p_end & encoded)){//detect one bit. remember transform to bool.
                p_begin = p_begin >> 1;
                p_end = p_end << 1;
            }else{
                break;
            }
        }
        if (p_end == p_begin)
            res.push_back(start_date);
        getNext(&start_date);
        encoded = toDec(start_date);
    }
    printf("palindromic date has been listed as follow \n");
    for (const auto i : res){
        printf("%s\n", asctime(&i));
    }
    return 0;
}
void getNext (tm* cur_date){
    cur_date->tm_mday += 16;
    int pre_mon = cur_date->tm_mon;
    mktime(cur_date);
    if (cur_date->tm_mon != pre_mon){
        cur_date->tm_mday = 1;
        searchStart(toDec(*cur_date), cur_date);
    }//turn to next month.
}
int toDec (const struct tm & cur_date){
    int encodeed = (cur_date.tm_year + 1900)*10000 + (cur_date.tm_mon + 1)*100
                   + cur_date.tm_mday;//Be careful the rule of date.
    return encodeed;
}
void searchStart(int encoded, tm* start_date){
    const int p = 0x0000000f;
    while((encoded & p) != 0x00000009) {
        encoded++;
        start_date->tm_mday++;
    }
}

这里顺便总结一下头文件time.h的一些常用日期处理用法(具体参见c++ reference):

在这里插入图片描述

time_t mktime (struct tm * timeptr);//将创建的tm转换为time_t,time_t是time_ptr所指向的对象与19700101相差的秒数,该过程
与localtime正相反。且将日期转换为合理的格式,例如20190435会被更改为20190505。
struct tm * localtime (const time_t * timer);//将时间转换为本地时间
char* asctime (const struct tm * timeptr);//返回表示时间的字符串形如:Www Mmm dd hh:mm:ss yyyy

值得一提的是,C /C++用 32 位的二进制数来表示以 1970 年 1 月 1 日为起点的时间,这也是上述程序以1970为起点的原因所在,如果向mktime传递的时间小于1970年,则会得到-1,所以如果处理1970年以前的时间则需要另谋他法。

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值