昨天写了一个关于位运算的困扰,今天又学习了一下才知道自己是多么的无知和愚蠢。
昨天的困惑:
16进制数:0X06AA4C
换算成24位2进制数:000001101010101001001100
数据定义:
//0~4 共5bit 春节日份
//5~6 共2bit 春节月份
//7~19 共13bit 13个月的大小月情况(如果无闰月,最后位无效),大月为1,小月为0
//20~23 共4bit 记录闰月的月份,如果没有闰月为0
进行取位运算得到月份和日期:
//计算春节的公历日期
int spring_ny_month = ( LUNAR_YEARS[year_index] & 0x60 ) >> 5; //取月份
int spring_ny_day = ( LUNAR_YEARS[year_index] & 0x1f); //取日期
我的疑惑为什么第一行能取到月份?为什么第二行能取到日期?
愚蠢的我所犯的错误:
000001101010101001001100把这个二进制数的左边当做低位。这是错误的根本。右边才是低位,那一切问题就都解决了。
0x60的二进制是01100000与上面的24位数进行位与运算,后再右移5位即得到24位数中的第6、7位,即月份,与原数据定义是相符的。日期的算法也就清楚了。
注:二进制的取位操作 (原理很容易理解,我却不知道)
逻辑与运算:两个数都为1时结果为1。
想取哪几位把那几位进行和1进行与运算,再移位即可。
如上面月份的计算:与0x60(二进制01100000)进行与运算,因为是第6、7位,所以要再右移5位。
日期计算:与0x1f(二进制:00011111)进行与运算,因为在最右边5位,所以不用移位。