位操作

本文总阅读量:
  1. 1. 位操作
  2. 2. 常见函数
    1. 2.1. set_bit
    2. 2.2. clear_bit
    3. 2.3. flip_bit
    4. 2.4. is_bit_set
    5. 2.5. modify_bit(见补码)
  3. 3. 补码(二补数)
  4. 4. 一些位操作
    1. 4.1. 是否为偶数
    2. 4.2. 返回有多少位不同
    3. 4.3. 四舍五入2的幂数
    4. 4.4. 交换两个数,效率比附tmp值低
    5. 4.5. 取绝对值

位操作

符号 名称 演示
& 1 & 1 = 1
1 & 0 = 0
0 & 0 = 0
1|1 = 1
1|0 = 1
0|0 = 0
^ 异或 1 ^ 1 = 0
1 ^ 0 = 1
0 ^ 0 = 0
~ ~1 = 0
~0 = 1
<< 左移 10101 << 2 =10100(相当于乘2)
>> 右移 10101 >> 2 =00101(相当于除2)

常见函数

set_bit

1
2
3
4
5
// 给position位设置为1
static int set_bit(int i,int position)
{
return i | 1 << position;
}

clear_bit

1
2
3
4
5
//给position位设置为0
static int clear_bit(int i,int position)
{
return i & ~(1 << position);
}

flip_bit

1
2
3
4
5
 //翻转position位的值
static int flip_bit(int i,int position)
{
return i ^ (1 << position);
}

is_bit_set

1
2
3
4
5
//判断position位是否为bit(1)
static int is_bit_set(int i,int position)
{
return i >> position & 1;
}

modify_bit(见补码)

1
2
3
4
5
//state1 是set_bit ;state0 时clear_bit
static int modify_bit(int i,int position,int state)
{
return (i & ~(1 << position)) | (-state & 1 << position);
}

补码(二补数)

补码用来表示负数的

https://zh.wikipedia.org/wiki/二補數

表示

补码使用有符号第一位表示正负,1为负 0为正,所以8有符号位数范围+-127,无符号位数255-0,无符号位数在C#中UInt32代表无符号32位

十进制值 二进制(二进制补码表示) 二补(2 - n)2
0 0000 0000 0000 0000
1 0000 0001 1111 1111
2 0000 0010 1111 1110
126 0111 1110 1000 0010
127 0111 1111 1000 0001
-128 1000 0000 1000 0000
-127 1000 0001 0111 1111
-126 1000 0010 0111 1110
-2 1111 1110 0000 0010
-1 1111 1111 0000 0001

为什么使用补码

二补数系统的最大优点是可以在加法或减法处理中,不需因为数字的正负而使用不同的计算方式。只要一种加法电路就可以处理各种有号数加法,而且减法可以用一个数加上另一个数的二补数来表示,因此只要有加法电路及二补数电路即可完成各种有号数加法及减法,在电路设计上相当方便。

如何进行表示

​ -1 原码:0000 0001

反码:1111 1110

补码=反码+1:1111 1111

一种简易的方式,可以找出二进位数字的二补数

先由最低位元开始找。

若该位元为0,将二补数对应位元填0,继续找下一位元(较高的位元)。

若找到第一个为1的位元,将二补数对应位元填1。

将其馀未转换的位元进行位元反相,将结果填入对应的二补数。

以0011 1100为例(图中的^表示目前转换的数字,-表示还不确定的位数):

原数字 补码

0011 1100 —- —0(此位元为0)

​ ^

0011 1100 —- –00(此位元为0)

​ ^

0011 1100 —- -100(找到第1个为1的位元)

​ ^

0011 1100 1100 0100(其馀位元直接反相)

^

因此其结果为1100 0100

一些位操作

一些提示

C#中不能直接将一串二进制数赋值给int32,可以用一下转换

Convert.ToInt32("1111",2)1111的二进制,即15 int32类型

Convert.ToString(15,2)15的二进制字符串,”1111“

是否为偶数

1
2
3
4
static bool is_even(int i)
{
return (i & 1) == 0;
}

返回有多少位不同

1
2
3
4
static int diff_bit(int a,int b)
{
return Convert.ToString(a ^ b, 2).Where(m => m == '1').Count();
}

四舍五入2的幂数

1
2
3
4
5
6
7
8
9
10
11
12
static int roundUpToNextPowerOfTwo(int x)
{
x--;
x |= x >> 1; // handle 2 bit
x |= x >> 2; // handle 4 bit numbers
x |= x >> 4; // handle 8 bit numbers
x |= x >> 8; // handle 16 bit numbers
x |= x >> 16; // handle 32 bit numbers
x++;

return x;
}

交换两个数,效率比附tmp值低

1
2
3
4
5
6
static void swapXor(ref int a,ref int b)
{
a ^= b;
b ^= a;
a ^= b;
}

取绝对值

1
2
3
4
5
static int myabs(int a)
{
int bit31 = a >> 31;
return (a ^ bit31) - bit31;
}