关于进制、原码反码补码以及位运算
程序员文章站
2022-03-13 18:21:47
...
对进制还有那些令人头疼的各种码(大学那会学数字逻辑到这些什么补码啊,8421码啊。。。学渣看到这就头疼ε=(´ο`*)))唉)的一些基本理解,下午闲的没事干把这些东西稍稍缕了一下,记录分享出来。
进制
所谓进制就是逢几进1,二进制就是逢二进一,只能用0、1表示;八进制逢八进一,只能用0~7表示;十进制逢十进一,只能用0~9表示,16进制同理,用0~9,A、B、C、D、E、F。
用二进制 表示十进制数 :
0 0 0 * 2^0
1 1 1 * 2^0 + 1 * 2^1
1 0 2 0 * 2^0 + 1 * 2^1
1 1 3 1 * 2^0 + 1 * 2^1
1 0 0 4 0 * 2^0 + 0 * 2^1 + 1 * 2^2
用八进制表示十进制数 :
0 0 0 * 8^0
1 1 1 * 8^0
2 2 2 * 8^0
3 3 3 * 8^0
... ... ......
7 7 7 * 8^0
1 0 8 0 * 8^0 + 1 * 8^1
1 1 9 1 * 8^0 + 1 * 8^1
用十六进制表示十进制数 :
1 1 1 * 16^0
2 2 2 * 16^0
... ... ......
9 9 9 * 16^0
A 10 A * 16^0
B 10 B * 16^0
... ... .....
F 15 F * 16^0
1 0 16 0 * 16^0 + 1 * 16^1
1 1 17 1 * 16^0 + 1 * 16^1
原码反码补码
一个整数为两个字节,也就是16bit,就是说一个数可以用16个0和1组成的数表示 例如: 1 : 0000 0000 0000 0001 ;
2 : 0000 0000 0000 0010 ;
但是在现实中有正数和负数,那么计算机应该怎么分正数和负数呢?
在计算机中数舍弃第一位当做符号位, 对于有符号位的 第一位表示符号为:0 表示正数,1 表示负数;后面十五位不变
那么 -1 :1000 0000 0000 0001 ;
-2 : 1000 0000 0000 0010 ;
我们现在来把-1 和正1相加:
我们现在来把-1 和正1相加:
-1 :1000 0000 0000 0001
+
1 :0000 0000 0000 0001
----------------------------------
1000 0000 0000 0010
是不是发现-1 和+1 相加结果等于-2了,这是怎么回事呢?
这里就要引入原码、反码和补码了,在计算机中所有的数存储都是以二进制的补码的形式存储的;
正数:原码 = 反码 = 补码
负数:反码 = 符号位不变,其他位取反
补码 = 反码 + 1
计算机中所有的运算,加减乘除啊位运算啊...都是用补码来进行计算的
补充一下:从补码转回原码跟原码转补码过程一样,符号位不变,其他位取反最后加1
【了解】 可以把减法用加法来算,只需设计加法器就好了。运算的时候都是用补码去运算的。 2-1 = 2+(-1)=0000 0000 0000 0010 +1111 1111 1111 1111
【了解】 为何要使用原码, 反码和补码 既然原码才是被人脑直接识别并用于计算表示方式, 为何还会有反码和补码呢? 首先, 因为人脑可以知道第一位是符号位, 在计算的时候我们会根据符号位, 选择对应加减,但是对于计算机,加减乘数已经是最基础的运算, 要设计的尽量简单。计算机辨别"符号位"显然会让计算机的基础电路设计变得十分复杂!于是人们想出了将符号位也参与运算的方法. 我们知道,根据运算法则减去一个正数等于加上一个负数, 即: 1-1 = 1 + (-1) = 0 , 所以机器可以只有加法而没有减法, 这样计算机运算的设计就更简单了.于是人们开始探索 将符号位参与运算, 并且只保留加法的方法
现在回到正题-1和1相加
1 原码 = 反码 = 补码 = 0000 0000 0000 0001
-1 原码 = 1000 0000 0000 0001
反码 = 1111 1111 1111 1110
+ 1
----------------------------------------------
补码 = 1111 1111 1111 1111下面来把这两个机器码相加
1 1000 0000 0000 0001
-1 1111 1111 1111 1111
真值 机器码
---------------------------------------
1 0000 0000 0000 0000
这个多出来的一位 计算机舍弃掉 得到了 0000 0000 0000 0000 也就是我们熟悉的0
位运算
- & 按位与
- | 按位或
- ^ 按位异或
- ~ 按位取反
- << 按位左移
-
>> 按位右移
<<按位左移
一个十进制数5 假如为一个字节(和两个字节的结果一样可以自己验证) 二进制为 0000 0101
现在将5向左移动一位:0000 1010 ------>值为10
再举个栗子,4的二进制位 : 0000 0100
将4左移一位 :0000 1000 ------> 值为8
通过上面两个例子,将一个数左移那么这个数变成了原来的两倍
下面我们来看看 << (左移)是怎么实现的
0000 0000 0000 0101
0000 0000 0000 0101000
----- ------
高位舍弃砍掉 低位补0
以上就是左移3位
按位左移的用途就是能很快速的计算一个数的次方,以为左移的时候会舍弃掉高位,所以有可能会改变一个数的正负性
>> 按位右移
所有的二进制位向右移n位,移出的位删除掉,移进的补符号位,右移不会改变一个数的正负性
0000 0010
0000 0010
右移跟左移的过程相反,相当于除2,一个数右移多少就相当于除2的多少次方 9>>2=9/2^2 = 2
& 按位与
全为1的时候才为1否则为0,举个通俗的例子来理解,你跟你女朋友结婚,要两个人都到场这个婚才能结成,只要一个不到这个婚就结不成了
| 按位或
只要有一个为1 就为1 ,也举个栗子吧,你跟你女朋友开车出去玩只要一个人开车这个车就能走了,不用两个人都一起开。
^ 按位异或
不同为1 当对应的二进位相异(不相同)时,结果为1,否则为0
~ 取反
说的通俗点就是0变1,1变0
这里要说一个比较特殊的例子 ~9=-10,下面来分析一下
9 : 0000 1001 计算机中的运算都是补码的形式运算的
取反 1111 0110 这是9取反后的补码,现在要做的就是通过补码得到原码
1000 1001
+1
-------------------------------
原码 1000 1010 -----------> -10