关于二进制操作很常见,很多笔试面试题中也有涉及,本篇主要围绕二进制翻转,二进制最高位判定和给定整数的二进制输出来探讨灵活使用二进制的&,|,!,》,《操作。
一、给定整数的二进制翻转
思路:可以考虑逐次翻转得到最终的翻转结果,具体做法,首先将所有二进制位奇偶位逐个翻转,然后以两位为一对(作为整体)奇偶对逐次翻转,依次。。。,最终完成翻转。
具体代码示例:
//bit_reverse:32位数按位反转函数
// 作用:把一个32位整数按位反转,即第1位转到第32位,第2位转到第31位,依次下去。
//算法实现:第一行代码为奇偶位相互交换;第二行为以两位为一单元,奇偶单元进行交换;第三行为以四位为一单元,奇偶单元进行交换;第四行为以八位为一单元,奇偶单元进行交换;最后一行为以十六位为一单元,奇偶单元进行交换。至此,32位反转完成,算法结束。
//注意:对于8位的翻转,方法是类似的,只是递增移位到 n >> 4即可。
static unsigned int bit_reverse(unsigned int n)
{
n = ((n >> 1) & 0x55555555) | ((n << 1) & 0xaaaaaaaa);
n = ((n >> 2) & 0x33333333) | ((n << 2) & 0xcccccccc);
n = ((n >> 4) & 0x0f0f0f0f) | ((n << 4) & 0xf0f0f0f0);
n = ((n >> 8) & 0x00ff00ff) | ((n << 8) & 0xff00ff00);
n = ((n >> 16) & 0x0000ffff) | ((n << 16) & 0xffff0000);
return n;
}
说明:本代码是以n为32位考虑的,根据输入数据所占bit位数的不同,可以选择相应需要移位到的级别。比如,对于char类型数据,只需要移位到 n >> 4 即可。
二、给定整数输出最高位为1的位置
思路:考虑通过移位来解决,每次将需要判定的bit位移位到最低位,如果移位后值为!=0,输出即可。
具体代码示例:
//find_most_significant_bit:求出32位数中从高位到低位的第一个bit=1的bit位
// 实现:按位右移判断
static int find_most_significant_bit(unsigned int n)
{
int length = sizeof(n) * 8;
for(int i = (length - 1); i >= 0; i--)
{
int value = n >> i;
if(value != 0)
{
return 1;
}
}
return 0;
}
说明:注意首先获取需要判定值的长度。int length = sizeof(n) * 8...
三、给定整数输出其二进制
1)网上复杂版本
static void printf_binary(unsigned int n)
{
int i;
for(i = 31; i >= 0; i--)
{
printf("%d", ((n & ((1<<(i+1))-1)) >> i) ? 1:0);
if(i%8 == 0)
{
printf(" ");
}
}
}
说明:具体还有待分析,感觉逻辑比较复杂,思路不够清晰。
2)不断除2模2求解
思路:首先计算出数据需要几位(有效位,不含0)来表示,申请对应大小缓存数组,然后通过不断地除和模运算得到每一位的值,保存在缓存数组,最后输出即可。
具体代码示例:
//printf_binary_bit_mod:以二进制形式输出整数
static void printf_binary_bit_mod(unsigned int n)
{
int bit_length = 0;
while (n >> bit_length)
{
bit_length++;
}
int *bit_arr = (int *)malloc(sizeof(int) * bit_length);
memset(bit_arr, 0, bit_length);
//或者如下代码进行内存初始化
//int *temp = bit_arr;
//for(int i = 0; i < bit_length; i++)
//{
// *(temp + i) = 0;
//}
int i = 0;
while(n)
{
//bit_arr[i] == *(bit_arr + i)
//核心部分即此
bit_arr[i++] = n % 2;
n = n / 2;
}
for(int i = (bit_length - 1); i >= 0; i--)
{
printf("%d", bit_arr[i]);
if(!(i % 8))
{
printf(" ");
}
}
}
说明:除2模2常规思路。
3)移位判定求解
思路:基本思路和2)类似,但是这里主要采用移位运算进行判定,感觉代码更清晰。
//printf_binary_bit_mod:以二进制形式输出整数
static void printf_binary_bit_shift(unsigned int n)
{
int bit_length = 0;
while (n >> bit_length)
{
bit_length++;
}
int *bit_arr = (int *)malloc(sizeof(int) * bit_length);
memset(bit_arr, 0, bit_length);
for (int i = 0; i < bit_length; i ++)
{
int value = n >> (bit_length - i - 1);
bit_arr[i] = value % 2;
}
for(int i = 0; i < bit_length; i++)
{
printf("%d", bit_arr[i]);
}
}
说明:首先通过不断地移位判定,计算出有效需要bit位长度,然后具体每一位的求解思路是,将这一位移位到最右边,然后进行模2运算,直接可以得到结果。因为
最右边bit位的值决定了整个移位后数据模2的结果,所以其结果必定是对应位的bit value。
当然,不通过移位,而是通过math.pow指数函数,求解也是可以的。
while (pow(2.0f, m) <= n) {
m++;
}
a = (int*)malloc(sizeof(int)*(m));
for (int i = 0; i < m; i ++)
{
a[i] = ((int)(n/pow(2.0f, m-i-1)))%2;
}
综合:具体的说到这里,要注意的是,多运用bit运算(移位。。。)
下面附上完整代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int find_most_significant_bit(unsigned int n);
unsigned int bit_reverse(unsigned int n);
void printf_binary(unsigned int n);
void printf_binary_bit_mod(unsigned int n);
void printf_binary_bit_shift(unsigned int n);
int main()
{
printf_binary_bit_shift(134);
return 0;
}
//bit_reverse:32位数按位反转函数
// 作用:把一个32位整数按位反转,即第1位转到第32位,第2位转到第31位,依次下去。
//算法实现:第一行代码为奇偶位相互交换;第二行为以两位为一单元,奇偶单元进行交换;第三行为以四位为一单元,奇偶单元进行交换;第四行为以八位为一单元,奇偶单元进行交换;最后一行为以十六位为一单元,奇偶单元进行交换。至此,32位反转完成,算法结束。
//注意:对于8位的翻转,方法是类似的,只是递增移位到 n >> 4即可。
static unsigned int bit_reverse(unsigned int n)
{
n = ((n >> 1) & 0x55555555) | ((n << 1) & 0xaaaaaaaa);
n = ((n >> 2) & 0x33333333) | ((n << 2) & 0xcccccccc);
n = ((n >> 4) & 0x0f0f0f0f) | ((n << 4) & 0xf0f0f0f0);
n = ((n >> 8) & 0x00ff00ff) | ((n << 8) & 0xff00ff00);
n = ((n >> 16) & 0x0000ffff) | ((n << 16) & 0xffff0000);
return n;
}
//find_most_significant_bit:求出32位数中从高位到低位的第一个bit=1的bit位
// 实现:按位右移判断
static int find_most_significant_bit(unsigned int n)
{
int length = sizeof(n) * 8;
for(int i = (length - 1); i >= 0; i--)
{
int value = n >> i;
if(value != 0)
{
return 1;
}
}
return 0;
}
//觉得这个写的比较复杂,逻辑不清晰,需要再进一步研究
//printf_binary:以二进制形式输出整数
// 实现:逐位右移判断
static void printf_binary(unsigned int n)
{
int i;
for(i = 31; i >= 0; i--)
{
printf("%d", ((n & ((1<<(i+1))-1)) >> i) ? 1:0);
if(i%8 == 0)
{
printf(" ");
}
}
}
//printf_binary_bit_mod:以二进制形式输出整数
static void printf_binary_bit_mod(unsigned int n)
{
int bit_length = 0;
while (n >> bit_length)
{
bit_length++;
}
int *bit_arr = (int *)malloc(sizeof(int) * bit_length);
memset(bit_arr, 0, bit_length);
//或者如下代码进行内存初始化
//int *temp = bit_arr;
//for(int i = 0; i < bit_length; i++)
//{
// *(temp + i) = 0;
//}
int i = 0;
while(n)
{
//bit_arr[i] == *(bit_arr + i)
//核心部分即此
bit_arr[i++] = n % 2;
n = n / 2;
}
for(int i = (bit_length - 1); i >= 0; i--)
{
printf("%d", bit_arr[i]);
if(!(i % 8))
{
printf(" ");
}
}
}
//printf_binary_bit_mod:以二进制形式输出整数
static void printf_binary_bit_shift(unsigned int n)
{
int bit_length = 0;
while (n >> bit_length)
{
bit_length++;
}
int *bit_arr = (int *)malloc(sizeof(int) * bit_length);
memset(bit_arr, 0, bit_length);
for (int i = 0; i < bit_length; i ++)
{
int value = n >> (bit_length - i - 1);
bit_arr[i] = value % 2;
}
for(int i = 0; i < bit_length; i++)
{
printf("%d", bit_arr[i]);
}
}