Binary
记录二进制及其应用
1. 二进制简介
以2
为基数的计数系统,通常用两个不同的数字0
和1
来表示;每个数字称为1
个二进制位或者比特(Bit
,Binary digit
的缩写)。
1. 二进制发展历史
- 现代的二进制计数系统由
Gottfried Wilhelm(von)Leibniz
于1679
年设计,在他1703
年发表的文章《论只使用付好0和1的二进制算术,兼论其用途及它赋予伏羲所使用的古老图形的意义》
。 1854
年,英国数学家George Bloole
发表了一篇里程碑式的论文《The Laws of Thought》
,其中详细介绍了一种代数化的逻辑系统,后人称之布尔代数
。它提出的逻辑演算在后来的电子电路设计中起基础性作用。1937
年,Claude Elwood Shannon
在麻省理工大学发表其硕士学位论文《继电器与开关电路的符号分析》
,其理论奠定了数字电路的理论基础。1937年11月
,任职于贝尔实验室的乔治·斯蒂比兹
发明了用继电器表示二进制的装置。它是第一台二进制电子计算机。
2. 算术运算
1. 加法(逢二进一)
0 + 0 = 0
0 + 1 = 1 + 0 = 1
1 + 1 = 0 (进位为1)
1 + 1 + 1 = 1(进位为1)
-
例如:
1110
和1011
相加过程如下:
2. 减法(借一有二)
0 - 0 = 0
1 - 1 = 0
1 - 0 = 1
0 - 1 = 1(借位为1)
-
例如:
1101
减去1011
的过程如下:
3. 乘法(参照十进制)
1 * 1 = 1
0 * 1 = 1 * 0 = 0
1 * 1 = 1
-
例如:
1001
和1010
相乘的过程如下:
4. 除法 (参照十进制)
0 ÷ 0 = 0
1 ÷ 0 = 0 (0 ÷ 1 无意义)
1 ÷ 1 = 1
-
例如:
100110
除以110
的过程如下:
5. 进制转换
小数示例:
3. 位运算
- 分析:位运算与算术运算的差异
- 位运算符只对整数起作用,如果一个运算子不是整数,会自动转为整数后再执行
- 位运算中,位于位之间不像加减运算那样有进位或错位的联系
1. 或(or)运算符
符号为|
,如果两位之一为 1
则设置每位为 1
,否则为0
2. 与(and)运算符
符号为 &
,如果两位都是 1
则设置每位为 1
,否则为0
3. 非 (not)运算符
符号为 ~
,表示对一个二进制位取反,1
取反为0
,反之
4. 异或(xor)运算符
符号为 ^
,如果两位只有一位为 1
则设置每位为 1
,否则为0
5. 左移(left shift)运算符
符号为 <<
,表示将一个数的二进制值向左移动指定的位数,尾部补0
,即乘以2
的指定次方
6. 右移(right shift)运算符
符号为 >>
,表示将一个数的二进制值向右移动指定的位数,尾部补0
,即除以2
的指定次方(最高位即符号位参与移动);如果是正数,头部全部补0
;如果是负数,头部全部补1
7. 头部补零的右移(zero filled right shift)运算符
符号为>>>
,表示一个数的二进制形式向右
移动时,头部一律补零,而不考虑符号位。该运算总是得到正值。与>>
区别主要在于负数。
4. 机器数中的原码、反码、补码(以8bit
为例)
1. 机器数
一个数在计算机中的二进制表示形式,叫做这个数的机器数,机器数是带符号的
2. 真值
带符号位的机器数对应的真正数值
3. 原码
原码就是符号位加上真值的绝对值,即第一位表示符号位,其余位表示数值
[+1]原 = 0000 0001
[-1]原 = 1000 0001
即8bit
的二进制数原码取值范围 [ -127 , 127 ]
4. 反码
正数的反码就是其本身
负数的反码是在原码的基础上,符号位不变,其余各个位取反
[+1]原 = [0000 0001]原 = [0000 0001]反
[-1]原 = [1000 0001]原 = [1111 1110]反
5. 补码
正数的补码就是其本身
负数的补码是在原码的基础上,符号位不变,其余各位取反,最后+1
(即在反码的基础上+1
)
[+1]原 = [0000 0001]原 = [0000 0001]反 = [1000 0000]补
[-1]原 = [1000 0001]原 = [1111 1110]反 = [1111 1111]补
-
思考:为何要使用原码、反码、补码🤔
人脑可以记住第一位为符号位,但是计算机无法辨别符号位;为了让符号位也参与计算,原码的正数部分带符号位运算是没有毛病的,但是负数呢 ?
- 1-1 = 1 + (-1) = [0000 0001]原 + [1000 0001]原 = [1000 0010]原 = -2 ?? 显然是不对的!
于是就诞生了反码
- 1-1 = 1 + (-1) = [0000 0001]原 + [1000 0001]原 = [0000 00001]反 + [1111 1110]反 = [1111 1111]反 = [1000 0000]原 = -0 🤔
发现用反码计算减法,结果的真值部分是正确的,而唯一的问题其实就出现在
0
这个特殊的数值上,虽然人们理解上+0
和-0
是一样的,但是0
带符号是没有任何意义的,而且会有[0000 0000]原和[1000 0000]原两个编码表示0于是又诞生了补码
- 1-1 = 1 + (-1) = [0000 0001]原 + [1000 0001]原 = [0000 00001]补 + [1111 1111]补 = [0000 0000]补 = [0000 0000]原 = 0 OK 没毛病了!
-
思考:关于补码的取值范围🤔
-
( -1 ) + ( -127 ) = [1000 0001]原 + [1111 1111]原 = [1111 1111]补 + [1000 0001]补 = [1000 0000]补
发现可以用[1000 0000]补表示-128
即补码的取值范围为[-128 , 127]
-
关于补码的取值范围,我总感觉这种解释逻辑还是有些牵强,网上查了很多资料,众说纷纭,但是总感觉有点怪怪的~若有错误请大佬指正,非常感谢!
此次笔记引用了以下网站:
https://zh.m.wikipedia.org/zh-hans/二进制
https://blog.csdn.net/qi_ming88/article/details/77677305
https://www.cnblogs.com/zhangziqiu/archive/2011/03/30/computercode.html
https://www.zhihu.com/question/20458542 注:补码取值范围问题