这两天有点闲,划水太严重。没有学习啥东西,跑去翻了一下书,看到 &
, |
, ^
, ~
, <<
,>>
这些位运算。然后就想起来了计算机的 原码
,反码
和 补码
。感觉写了两年的前端,我好像早已把这些东西抛之脑后,对于位运算我好像也没用过。写这个算是给自己复习,记录一下吧。
在这之前我们可以先了解一下机器数和真值。机器数是将符号"数字化"的数,是数字在计算机中的二进制表示形式。机器数有两个特点:一是符号数字化,二是其数的大小受机器字长的限制。真值是指在一定的时间及空间(位置或状态)条件下,被测量所体现的真实数值。真值是一个变量本身所具有的真实值,它是一个理想的概念,一般是无法得到的。所以在计算误差时,一般用约定真值或相对真值来代替。通常所说的真值可以分为“理论真值”、“约定真值”和“相对真值”。
计算机中的符号数有三种表示方法,即原码、反码和补码。三种表示方法均有符号位和数值位两部分,符号位都是用0表示“正”,用1表示“负”,而数值位,三种表示方法各不相同。
数值 | 原码 | 反码 | 补码 |
---|---|---|---|
+1 | 0000 0001 | 0000 0001 | 0000 0001 |
-1 | 1000 0001 | 1111 1110 | 1111 1111 |
&
只有对应的两个二进位都为1时,结果位才为1。参与运算的两个数均以补码出现。
5 & 6
0000 0101
0000 0110
--------
00000100
// 将 0000 0100 转换为十进制为 4
-5 & 6
1111 1011
0000 0110
--------
0000 0010
// 将 0000 0010 转换为十进制为 2
|
只要对应的两个二进位有一个为1时,结果位就为1。当参与运算的是负数时,参与两个数均以补码出现。
3 | 4
0000 0011
0000 0110
---------
0000 0111
// 将 0000 0111 转换为十进制为 7
-3 | 4
1111 1101
0000 0100
---------
1111 1101
// 逐位取反 + 1
1000 0011
// 将 1000 0011 转换为十进制为 -3
^
如果对应的两个二进位值不相同,则异或结果为1。如果对应的两个二进位值相同,异或结果为0。
7 ^ 8
0000 0111
0000 1000
---------
0000 1111
// 将 0000 1111 转换为十进制为 15
-7 ^ 8
1111 1001
0000 1000
---------
1111 0001
// 逐位取反 + 1
1000 1111
// 将 1000 1111 转换为十进制为 -15
~
二进制值每一位取反,0变1,1变0。
~10
0000 1010
---------
0111 0101
// 逐位取反 + 1
1000 1011
// 将 1000 1011 转换为十进制为 -11
~-10
1000 1010
---------
1111 0110
// 逐位取反 + 1
0000 1001
// 将 0000 1001 转换为十进制为 9
<<
参加运算的数换算为二进制后,进行左移运算,用来将一个数各二进制位全部向左移动若干位。
10 << 2
0000 1010
---------
0010 1000
// 将 0010 1000 转换为十进制为 40
-10 << 2
1000 1010
---------
// 先求补码,按位取反 + 1
1111 0110
// 左移 2 位
1101 1000
// 求补码,按位取反 + 1
1010 1000
// 将 1010 1000 转换为十进制为 -40
>>
参加运算的数换算为二进制后,进行左移运算,用来将一个数各二进制位全部向右移动若干位。
10 >> 2
0000 1010
---------
0000 0010
// 将 0000 0010 转换为十进制为 2
-10 >> 2
1000 1010
---------
// 先求补码,按位取反 + 1
1111 0110
// 右移 2 位
1111 1101
// 求补码,按位取反 + 1
1000 0011
// 将 1010 1000 转换为十进制为 -3
最高位为符号位!