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

  • Post author:
  • Post category:其他




问题描述:

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

例)日期为1966年7月13日时 ① YYYYMMDD格式→

19660713

② 转换成二进制数→

1001010111111111110101001

③ 逆序排列→

1001010111111111110101001

④ 把逆序排列得到的二进制数转换成十进制数→

19660713



分析:

处理日期多麻烦哦,我们交给库函数处理,嘿嘿。剩下的我们需要考虑怎样优化算法。先看时间转化为二进制的范围

19641010



1001010111111111110101001

‬,

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年以前的时间则需要另谋他法。



版权声明:本文为QSTARTmachine原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。