二进制
整数
- 十进制数转二进制数:除二取余倒记法
- 二进制数转十进制数:按权相加法
比如计算 13
的二进制数:
ini
13 / 2 = 6 ... 1
6 / 2 = 3 ... 0
3 / 2 = 1 ... 1
1 / 2 = 0 ... 1
所以得到的结果为 1101
将 1101
转换为十进制数:
ini
1 * 2^3 + 1 * 2^2 + 0 * 2^1 + 1 * 2^0 = 13
小数
小数的二进制数转换也是一样的,只不过是除以 2
变成乘以 2
,然后是正记法
比如计算 0.78125
的二进制数:
ini
0.78125 * 2 = 1.5625 ... 1
0.5625 * 2 = 1.125 ... 1
0.125 * 2 = 0.25 ... 0
0.25 * 2 = 0.5 ... 0
0.5 * 2 = 1 ... 1
所以得到的结果为 0.11001
将 0.11001
转换为十进制数:
ini
1 * 2^-1 + 1 * 2^-2 + 0 * 2^-3 + 0 * 2^-4 + 1 * 2^-5 = 0.78125
原码
原码是有符号数的一种表示方法,第一位是符号位,0
表示正数,1
表示负数
补码
正数的补码等于原码
负数的补码有两种计算方法:
- 符号位不变,原码的反码 + 1
- 比如十进制数
-21
- 原码:
10010101
- 反码:
11101010
- 补码:
11101011
- 原码:
- 比如十进制数
2^(n+1) + x
- 十进制数
-21
2^8 - 21
2^8
的二进制:10000000
21
的二进制:10010101
- 得到补码:
11101011
- 十进制数
小数的补码算法和整数的补码一样:
- 正数的补码等于原码
- 负数的补码等于原码的反码 + 1
反码
反码有一个作用就是把减法转换为加法
正数的反码等于原码,负数的反码等于原码的符号位不变,其他位取反
上面计算原码的补码的时 2^(n+1) + x
,这种方案 x
是负数的话,就会变成减法运算,而减法运算在计算机中是比较复杂的
所以使用反码就可以消除运算中的减法运算
定点数和浮点数
定点数
小数点固定在某个位置的数称为定点数
小数位在符号位之后,称为定点小数
小数位在数值位之后,称为定点整数
浮点数
如果这个数值比较大,会超过定点数的表示范围,这时候就需要使用浮点数
浮点数的表示方法是科学计数法,分为四部分:
- 阶码符号位
- 阶码
- 尾数符号位
- 尾数(尾数是补码,必须是纯小数,最高位必须是
1
)
比如:0.110101 * 2^6
,小数点前面是符号位,小数点后面是尾数
用 2
个字节来表示浮点数
- 阶码符号位:占用
1
位 - 阶码:占用
4
位 - 尾数符号位:占用
1
位 - 尾数:占用
10
位
正数
小数 0.1015625
转换成二进制数
ini
0.1015625 * 2 = 0.203125 ... 0
0.203125 * 2 = 0.40625 ... 0
0.40625 * 2 = 0.8125 ... 0
0.8125 * 2 = 1.625 ... 1
0.625 * 2 = 1.25 ... 1
0.25 * 2 = 0.5 ... 0
0.5 * 2 = 1 ... 1
得到的结果为 0.0001101
0.0001101
规格化:
0.1101000000 * 2^-3
正数的补码还是原码
阶码符号位 | 阶码 | 尾数符号位 | 尾数 |
---|---|---|---|
1 |
0011 |
0 |
1101000000 |
负数
整数 -54
转换成二进制数
ini
54 / 2 = 27 ... 0
27 / 2 = 13 ... 1
13 / 2 = 6 ... 1
6 / 2 = 3 ... 0
3 / 2 = 1 ... 1
1 / 2 = 0 ... 1
得到的结果是:-110110
,用 1
表示负数 1,110110
1,110110
规格化:
1.1101100000 * 2^6
负数的补码是原码的反码+1
所以 1.1101100000 * 2^6
转换成补码是 1.0010100000 * 2^6
阶码符号位 | 阶码 | 尾数符号位 | 尾数 |
---|---|---|---|
0 |
0110 |
1 |
0010100000 |
表示范围
假设阶码有 n
位,尾数有 m
位
- 阶码的范围
-(2^n - 1)
~2^n - 1
- 尾数的范围
- 负数
-(1 - 2^-m)
~-(2^-m)
- 正数
2^-m
~1 - 2^-m
- 负数
上溢 | 负数最小值 | 负数最大值 | 下溢 | 下溢 | 下溢 | 正数最小值 | 正数最大值 | 上溢 |
---|---|---|---|---|---|---|---|---|
- | -(1 - 2^-m) * 2^(2^n - 1) |
-(2^-m) * 2^-(2^n - 1) |
- | 0 |
- | (2^-m) * 2^-(2^n - 1) |
(1 - 2^-m) * 2^(2^n - 1) |
- |
定点数加减法运算
定点数加法运算用补码运算,如果符号位发生进位,则丢弃符号位
单符号位如果符号位发生进位了,不知道有没有发生溢出,所以就有了双符号位,如果双符号在计算后不相同,就说明有溢出
整数加法
例如:A
的值为 -110010
,B
的值为 001101
,求 A + B
A
:-110010
补齐符号位1,110010
,它的补码是1,001110
B
:001101
补齐符号位0,001101
,它的补码是0,001101
A + B
=> A
的补码 + B
的补码 1,001110 + 0,001101
=> 1,011011
这个 1,011011
是补码,转换成原码就是 1,100101
验证一下 A
的十进制数是 -50
,B
的十进制数是 13
,A + B
的结果是 -37
1,100101
转换成十进制数是 -37
所以 A + B = 1,011011
小数加法
例如:A
的值为 -0.1010010
,B
的值为 0.0110100
,求 A + B
A
:-0.1010010
补齐符号位1,0.1010010
,它的补码是1,1.0101110
B
:0.0110100
补齐符号位0,0.0110100
,它的补码是0,0.0110100
A + B
=> A
的补码 + B
的补码 1,1.0101110 + 0,0.0110100
=> 1,1.1100010
这个 1,1.1100010
是补码,转换成原码就是 1,0.0011110
验证一下 A
的十进制数是 -0.640625
,B
的十进制数是 0.40625
,A + B
的结果是 -0.234375
1,0.0011110
转换成十进制数是 -0.234375
所以 A + B = 1,1.1100010
双符号位有溢出
例如:A
的值为 -10010000
,B
的值为 -11010000
,求 A + B
A
:-10010000
补齐符号位11,10010000
,它的补码是11,01110000
B
:-11010000
补齐符号位11,11010000
,它的补码是11,00110000
A + B
=> A
的补码 + B
的补码 11,01110000 + 11,00110000
=> 110,10100000
符号位最高位的 1
舍弃,剩下 10
,符号位最高位不同,说明 A + B
发生了溢出
减法运算
减法运算,要转换成加法运算,所以减数的补码**取反(包括符号位)加 1
**就能变成加法运算
换句话说,减数的补码 = 减数的原码 + 减数的符号位取反
例如 A
的值为 11001000
,B
的值为 -00110100
,求 A - B
A
:11001000
补齐符号位00,11001000
,它的补码是00,11001000
B
:-00110100
补齐符号位11,00110100
,它的补码是11,11001100
- 将
B
的补码取反(包括符号位)加1
,得到00,00110100
- 将
A - B
=> A
的补码 + -B
的补码 00,11001000 + 00,00110100
=> 00,11111100
这个 00,11111100
是补码,转换成原码就是 00,11111100
验证一下 A
的十进制数是 200
,B
的十进制数是 -52
,A - B
的结果是 252
00,11111100
转换成十进制数是 252
浮点数加减法
浮点数加减法要分为 5
个步骤:
- 对阶
- 尾数求和
- 尾数规格化
- 舍入
- 溢出判断
值 | 阶码符号位 | 阶码 | 尾数符号位 | 尾数 | |
---|---|---|---|---|---|
A | 0.1101 * 2^1 |
00 |
01 |
00 |
1101 |
B | -0.1010 * 2^3 |
00 |
11 |
11 |
1010 |
加码+1,尾数右移,阶码-1,尾数左移
对阶
对阶的目的是使得两个浮点数阶码一致,从而使得尾数可以进行运算
因为浮点数的小数位与阶码有关,如果阶码不整齐,就无法进行运算
对阶操作:小阶对齐大阶
A
的阶码是1
,对应的二进制数是01
B
的阶码是3
,对应的二进制数是11
A
的阶码需要变成 11
,所以 A
的尾数需要右移 2
位,变为 0.0011
值 | 阶码符号位 | 阶码 | 尾数符号位 | 尾数 | |
---|---|---|---|---|---|
A | 0.1101 * 2^1 |
00 |
11 |
00 |
0011(01) |
B | -0.1010 * 2^3 |
00 |
11 |
11 |
1010 |
由于这里只有 4
位,所以 A
的尾数右移后 01
需要被舍弃
尾数求和
尾数求和的方法和定点数的加减法一致
A + B
的结果是 11,1011
记为 S
,这里的 S
是补码
阶码符号位 | 阶码 | 尾数符号位 | 尾数 | |
---|---|---|---|---|
S |
00 |
11 |
11 |
1001 |
尾数规格化
尾数规格化分两种情况
- 如果
S > 0
,需满足00.1xxxxx
- 如果
S < 0
,需满足11.0xxxxx
如果不满足条件需要小数部分需要进行左移,同时阶码需要发生变化
阶码符号位 | 阶码 | 尾数符号位 | 尾数 | |
---|---|---|---|---|
S |
00 |
10 |
11 |
(1)0010 |
S
的的尾数是 11.0010
,原码 11.1110
,所以 A + B
的值是-0.1110
尾数规格化(右移)
尾数规格化,一般都是左移,只有在双符号位不一致的情况下,才进行右移
右移的话需要进行舍入操作,在二进制中的舍入是 0
舍 1
入法
例如:
10.10110111
右移一位,符号位补1
,11.01011011(1)
,阶码需要+1
- 如果是
10
,右移符号位补1
,小数位补0
- 如果是
01
,右移符号位补0
,小数位补1
- 如果是
- 由于舍弃的是
1
,所以还需要+1
,得到的结果是11.01011100
0
舍 1
入可能会有溢出
溢出判断
在浮点数中判断溢出:在规格化后判断阶码的符号位是否一致,如果一致就没有溢出,如果不一致就溢出了