编程小技巧

    返回首页    发表留言
本文作者:李德强
          技巧十:位移运算
 
 

        今天跟大家分享的小技巧是关于位移运算的。大多数数的编程语言都采用“>>”和“<<”运算符来对变量做位移运算,也就是我们通常所说的“右移”和“左移”。顾名思义,右移运算表示将一个数的每一位都向右移动一位,而左移则表示将一个数的每一位都向左移动一位。

 

        一、无符号数的位移运算:

0001 1010 右移一位(>>1) 0000 1101
26                      13
0000 1101 右移一位(>>1) 0000 0110
13                      6
0000 0110 右移一位(>>1) 0000 0011
6                       3
0000 0011 右移一位(>>1) 0000 001
2                       1
0000 0001 右移一位(>>1) 0000 0000
1                       0

        很显然右移运算的结果等于原来数值的1/2,这里有一个细节需要注意,对于无符号数的右位移运算最高位是补0的,所以在经过了有限次右移运算后,此无符号数则会变为0。

        我们再来看看左移运算的结果:

0001 1010 左移一位(<<1) 0011 0100
26                      52
0011 0100 左移一位(<<1) 0110 1000
52                      104
0110 1000 左移一位(<<1) 1101 0000
104                     208
1101 0000 左移一位(<<1) 1010 0000
208                     160
1010 0000 左移一位(<<1) 0100 0000
160                     64
0100 0000 左移一位(<<1) 1000 0000
64                      128
1000 0000 左移一位(<<1) 0000 0000
128                     0

        通常对无符号数左移运算的结果等于这个数的2倍,但也不是绝对的,我们看到当208向右位移一位之后结果为160,这是为什么呢?原因很简单,在对无符号数向左位移运算时最低位补0,但高位则会溢出,也就是说1101 0000 (208)左移一位 原来最高位的1溢出了,于是结果就变成了1010 0000(160)左移的结果非但不是原来的2倍,反而变小了,所以我们在做位移运算时一定要注意变量的类型,在内存中的存储大小,一定要考虑到出现高位溢出的情况。

 

       二、有符号数的位移运算:

        先来看看对一个负数做右位移运算:

1001 1100 右移一位(>>1) 1100 1110
-100                    -50
1100 1110 右移一位(>>1) 1110 0111
-50                     -25
1110 0111 右移一位(>>1) 1111 0011
-25                     -13
1111 0011 右移一位(>>1) 1111 1001
-13                     -7
1111 1001 右移一位(>>1) 1111 1100
-7                      -4
1111 1100 右移一位(>>1) 1111 1110
-4                      -2
1111 1110 右移一位(>>1) 1111 1111
-2                      -1
1111 1111 右移一位(>>1) 1111 1111
-1                      -1

        在上面对负数的位移运算中,我们可以看到负数的位移运行跟正数不同,每右移一位结果是原来数值的2倍,并且为了保证负数的符号不变所以高位补1,当-2右移一位后结果为-1,而-1的补码为1111 1111,接下来我们再对-1进行一次右位移运算,结果仍然是-1,因为高位仍然补1,所有的bit位均为1。所以我们在对负数做位移做运算时一定要考虑到负数的符号位。

        我们再来看看对负数的左位移运算:

1001 1100 左移一位(<<1) 0011 1000
-100                    56
0011 1000 左移一位(<<1) 0111 0000
56                      112
0111 0000 左移一位(<<1) 1110 0000
112                     -32
1110 0000 左移一位(<<1) 1100 0000
-32                     -64
1100 0000 左移一位(<<1) 1000 0000
-64                     -128
1000 0000 左移一位(<<1) 0000 0000
-128                    0
0000 0000 左移一位(<<1) 0000 0000
0                      0

        有两个地方我们需要注意一下:

        第一,高位溢出后计算机并不保留原符号位的符号,而只把位移后符号位的值做为新的符号。也就是说:1001 1100 (-100)左移一位0011 1000(56)原来最高位是1,表示这是一个负数,值为-100,但经过了一次左位移运算之后,最高位变成了0,于是这个数则变成了一个正数,值为56;接下来0111 0000 (112)左移一位  1110 0000(-32)原来最高位是0,表示这是一个正数,值为112,但经过了一次左位移运算之后,最高位变成了1,于是这个数则变成了一个负数,值为-32。

        第二,在对有符号数的左位移运算时,最低位补0。所以经过有限次的左位移运算之后,结果将会是0。

    返回首页    返回顶部
  看不清?点击刷新

 

  Copyright © 2015-2018 问渠网 辽ICP备15013245号