何为一个整数二进制奇数位和偶数位
想要完成解题,我们首先要知道一个整数二进制奇数位和偶数位,具体代表着哪一位
对于一个32位的整型,它的下标是从 0 ~ 31 的,总共32位。
其中下表为0的位是最右边的位(即最低有效位,LSB)
而下标为31的位是最左边的位(即最高有效位,MSB)
当我们说 “偶数位” 的时候,我们指的是下标为偶数( 0 , 2 , 4 …… 30 )的位
当我们说 “奇数位” 的时候,我们指的是下标为奇数( 1 , 3 , 5 …… 31 )的位
步骤1:定义掩码
我们要把一个整数二进制奇数位和偶数位交换,首先想到的就是找掩码来进行操作
何为掩码?掩码通常是一个二进制数,用于选择和屏蔽特定的位
在交换一个整数二进制奇数位和偶数位问题中,掩码用来选则出整数中的奇数位和偶数位。具体我们要用到两个掩码:
1.1偶数位掩码:
一个掩码,其中偶数索引位(从右边数起,第一位开始)是1,其余为是0。对于一个32位整数,它通常是:0x55555555
0101 0101 0101 0101 0101 0101 0101 0101 0101 0101 //(二进制)5 5 5 5 5 5 5 5 5 5 //(十六进制)
偶数位掩码的作用就是将整数所有的偶数位保留下来( 0 , 2 , 4 …… 30 ),
而奇数位全部清零( 1 , 3 , 5 …… 31 ),具体我们可以使用:
按位与 (&)来操作
通过这样的操作,我们就将 所有的偶数位保留下来,而奇数位全部清零了
1.2奇数位掩码:
一个掩码,其中奇数位索引的位为1,其余是0对于一个32位整数,它通常是:0xAAAAAAAA
奇数位掩码的作用就是将整数所有的奇数位保留下来,而奇数位全部清零。
步骤2:位操作
接下来,我们使用位操作来交换奇数位和偶数位
- 将整数与偶数位掩码0x55555555进行按位与操作(&),得到只包含偶数位信息的数。
- 将这个只包含偶数位信息的数左移一位(<< 1),使原来的偶数位占据奇数位的位置。
- 同时,将整数与奇数位掩码0xAAAAAAAA进行按位与操作(&),得到只包含奇数位信息的数。
- 将这个只包含奇数位信息的数右移一位(>> 1),使原来奇数位占据偶数位的位置
步骤3:合并结果
最后,我们将左移后的偶数位和右移后的奇数位通过:
按位或操作( | ),或者加号( + )合并起来,得到最终交换了奇数位和偶数位的整数。
宏的最终实现
#define SWAPa(x) ( \(((x) & 0x55555555) << 1) | \(((x) & 0xAAAAAAAA) >> 1) \
)
#define SWAb(x) ( \(((x) & 0x55555555) << 1) + \(((x) & 0xAAAAAAAA) >> 1) \
)
int main() {printf("%d\n", SWAPa(5));printf("%d\n", SWAPa(5));printf("%d\n", SWAPa(10));printf("%d\n", SWAPa(10));return 0;
}
输出结果:10 10 5 5