计算机原理之位运算及二十余种常用技巧

位运算和常用技巧

作者:humorchen
CSDN博客地址:https://blog.csdn.net/HumorChen99

位运算

按二进制位进行逐个运算

与 &符号

全部为1则为1,否则为0

1 & 1 = 1

1 & 0 = 0

0 & 1 = 0

0 & 0 = 0

 100101
&
 010110
=010100

或 |符号

否则为0则为0,有一个为1则为1,

1 | 1 = 1

1 | 0 = 1

0 | 1 = 1

0 | 0 = 0

 100101
|
 010110
=110111

非 ~符号

~0 = 1 ~1 = 0 反过来

~100101
=011010

左移 << 符号

向左移动多少个位,右边的缺位补0(如果为负数,则取负数补码最右边5位对应的正数值)

例如java中 1<<-1,-1的补码是11111111111111111111111111111111111,取最右边5位,0b11111,值为31,那么1<<-1就相当于1<<31

往左移动1位就相当于乘以2

整数
十进制     3
二进制补码  0000000000000000000000000000000011
3<<1
二进制补码  0000000000000000000000000000000110 = 6

右移 >>符号

向右移动多少个位,左边的缺位符号位补符号位

往又移动1位就相当于除以2(没有小数的)

整数
十进制     3
二进制补码  0000000000000000000000000000000011

常用技巧

获得int最大值

(1<<31)-1
~(1<<31)
(1<<-1)-1
~(1<<-1)

令x = 1<<31 = 10000000000000000000000000000000
x -1 = x + (-1) =
10000000000000000000000000000000
+
11111111111111111111111111111111

= 01111111111111111111111111111111

获得int最小值

1<<31
1<<-1

1<<31= 10000000000000000000000000000000 即是最小值,正0和负0没有必要有两个,因此负0作为最小值,补码为32个1的值-1。

获取long最大值

和int同理,不解释了,只是int 4个字节32个位,long 8个字节,64个位。

(1<<63)-1
(1<<-1)-1

获取long最小值

1<<63
1<<-1

乘2运算

往左移1位就是乘以2

3<<1 = 6

除2运算

往右移一位就是除以2(负奇数不可以)

3>>1 = 1
  • 3 = 00000000000000000000000000000011 >> 1 = 00000000000000000000000000000001 = 1

  • -4 = 10000000000000000000000000000100(原) = 11111111111111111111111111111011(反)

= 11111111111111111111111111111100(补) >> 1 = 11111111111111111111111111111110(补) =

11111111111111111111111111111101(反) = 10000000000000000000000000000010(原) = -2

  • -3 = 10000000000000000000000000000011(原) = 11111111111111111111111111111100(反)

= 11111111111111111111111111111101(补) >> 1 = 11111111111111111111111111111110(补) =

11111111111111111111111111111101(反) = 10000000000000000000000000000010(原) = -2

因此负奇数不能使用这个方法来除2!

乘以2的m次方

乘以2的m次方就往左移动m位即可

3<<m

除以2的m次方

除以2的m次方就往右移动m位即可(负奇数不可以)

3>>m

判断数是不是奇数

n&1 == 0

3&0= 11 & 01 = 01 =1 != 0

4&1 = 100 & 001 = 000 =0

不用第三个数交换两个数

a ^= b
b ^= a
a ^= b

第一行a ^= b

-> a = a^b b = b

第二行b ^= a

b = b (ab) = a

-> a = a^b b = a

第三行a ^= b

a = (a^b) ^ (a) = b

-> a = b b = a

交换完成

取绝对值

(n ^ (n >> 31)) - (n >>31)

例如

  • n= 3

(3 ^ (3 >> 31)) - (3 >> 31)

= (3 ^ (3 >> 31)) - 0

= (3 ^ (3 >> 31))

= 3 ^ 0

= 11 ^ 0

= 11 = 3

-3 = 10000000000000000000000000000011(原) 
=   11111111111111111111111111111100(反)
= 11111111111111111111111111111101(补) 

-3 >> 31 = 11111111111111111111111111111101 >>31 
= 11111111111111111111111111111111 = -1
  • n = -3

(-3 ^ (-3 >> 31)) - (-3 >> 31)

=(-3 ^ (-1)) - (-1)

= (11111111111111111111111111111101 ^ 11111111111111111111111111111111) +1

=00000000000000000000000000000010 +1 = 00000000000000000000000000000011 = 3

判断符号是否相同

x ^ y >= 0

主要是符号位

  • 0 ^ 0 = 0

  • 0 ^ 1 = 1

  • 1 ^ 0 = 1

  • 1 ^ 1 = 0

计算2的n次方

1<<n

判断一个数是不是2的n次幂

n > 0 ? (n & (n-1) ) == 0 : false
  • 4

100 & (011) = 000 = 0

  • 3

11 & (10) = 10 = 2 != 0

对2的n次方取余

m & ((1<<n)-1)

m = 5 n = 2

1 << 2 = 4 = 100

101 & (100 -001) = 101 & (011) = 001 = 1

求两个数平均值

(x+y)>>1

从低位到高位,取n的第m位的值?

(n>>(m-1)) & 1

例如取 十进制数11 的二进制的第2位

11 = 1011

(1011>>(2-1)) & 1

=(101) & 1

=101 & 001

=001 = 1

因此11的二进制的第2位数为1

从低位到高位,将n的第m位设置为1

n | (1 << (m-1))

1 << 2 = 100

11 = 1011

11 | 0100 = 1011 | 0100 = 1111

其实就是给一个000… 1…0的数和原数做或运算,那个位自然就变1了。

从低位到高位,将n的第m位设置为0

n & ~(1 << (m-1))

1 << 1 = 10

11 = 1011

1011 & ~(10)

= 1011 & 01

= 1010 = 10

其实就是给一个000… 1…0的数和原数做或运算,那个位自然就变1了。

不用+对数n做+1操作

-~n

例如 5 = 00000000000000000000000000000101(补)

~5 = 11111111111111111111111111111010 (补) = 11111111111111111111111111111001(反)=10000000000000000000000000000110(原)

-~5 = -(10000000000000000000000000000110(原)) = 00000000000000000000000000000110(原) = 6

对数n做-1操作

~-n

例如 n =5

-5 = 10000000000000000000000000000101(原) = 11111111111111111111111111111010(反)= 11111111111111111111111111111011(补)

~-5 = ~(11111111111111111111111111111011(补))=00000000000000000000000000000100(补)=4

取相反数

~n+1

例如 n = 5

5 = 00000000000000000000000000000101(补)

~5 = 11111111111111111111111111111010(补)

~5+1=11111111111111111111111111111010(补) +1 = 11111111111111111111111111111011(补)=

11111111111111111111111111111010(反) = 10000000000000000000000000000101(反) =-5

posted @ 2021-07-26 11:35  HumorChen99  阅读(6)  评论(0编辑  收藏  举报  来源