计算机基础知识总结第一篇,先从最害怕的计算机组成原理开始。
为了防止写过就忘(其实还是会忘记T……T)。
计算机中数的表示
假设该计算机使用八位表示数,其中一位是符号位,其余7位表示数值。
机器数与真值
机器数:一个数字在机器中的二进制表示形式,带有符号位
真值:带符号位的机器数对应的真正的数值,机器数不一定就等于真值
原码
形式: 【符号位】【真值的绝对值】
eg.
+1 = 0 0000001
-1 = 1 0000001
8位表示的范围: [1 1111111, 0 1111111],即[-127, 127]
n位表示的范围: [-2^(n-1),2^(n-1)]
零:
+0 = 0 0000000
- 0 = 1 0000000
反码
形式:
(正数)【0】【真值的绝对值】= 原码
(负数)【1】【原码数值位按位取反】
eg.
+1 = 0 0000001原码 = 0 0000001反码
-1 = 1 0000001原码 = 1 1111110反码
8位表示的范围: [1 0000000, 0 1111111],即[-127, 127]
n位表示的范围: [-2^(n-1),2^(n-1)]
零:
+0 = 0 0000000
- 0 = 1 0000000
补码
形式:
(正数)【0】【真值的绝对值】= 原码
(负数)【1】【原码数值位按位取反 + 1】
eg.
+1 = 0 0000001原码 = 0 0000001补码
-1 = 1 0000001原码 = 1 1111111补码
8位表示的范围: [1 0000000, 0 1111111],即[-128, 127]
n位表示的范围: [-2^(n-1),2^(n-1)]
零:
+0 = 0 0000000
- 0 = 0 0000000
数的存储
大端模式
数的高字节存储在低地址端,低字节存储在高地址端
小端模式
数的低字节存储在低地址端, 高字节存储在高地址端
实例
16bit宽的数0x1234在Little-endian模式(以及Big-endian模式)CPU内存中的存放方式(假设从地址0x4000开始存放)为:
内存地址 | 小端模式 | 大端模式 |
---|---|---|
0x4000 | 0x34 | 0x12 |
0x4001 | 0x12 | 0x34 |
32bit宽的数0x12345678在Little-endian模式以及Big-endian模式)CPU内存中的存放方式(假设从地址0x4000开始存放)为:
内存地址 | 小端模式 | 大端模式 |
---|---|---|
0x4000 | 0x78 | 0x12 |
0x4001 | 0x56 | 0x34 |
0x4002 | 0x34 | 0x56 |
0x4003 | 0x12 | 0x78 |
易错点
肘子最容易错的地方是常常分不清数的最高位,唉
数的运算
假设该计算机使用八位表示数,其中一位是符号位,其余7位表示数值。
加减法
减法等于加上减数的补码
eg.
710 + 610 =
0 000 01112+ 0 000 01102 = 0 000 11012
= 1310
710 - 610 = 710 + (-6)10
0 000 01112- 0 000 01102
=0 000 01112+ 1 111 10102 = 0 000 00012
= 110
溢出
异号相加,同号相减均不溢出
异号相加所得结果介于两个操作数之间,同号相加的问题则可以转化为异号相加问题
所以,溢出的情况如下
正正相加得负,负负相加得正
正负相减得负,负正相减得正
乘法
【无符号】计算10002与10012
乘数,被乘数存在负数,记住符号位,转化为正数,即原码参与运算
假如忽略符号位,被乘数N位,乘数M位,积为N+M位
符号位不参与运算,符号相异,积为负
示例中按道理结果应该是8位,因为最高位的0,因为中间积相加没有进位
除法
【无符号】计算10010102除以10002
【有符号】
除数,被除数存在负数,记住符号位,转化为正数,即原码参与运算
符号位不参与运算
源操作数符号相异,商为负,否则商为正
余数与被除数符号相同
注意,余数可负可正,这与“余数必须为正”有所区别
浮点数
浮点表示
形式
(-1)S * (1 + F) * 2E
其中,F为小数域的值,E为指数域的值
单精度(32位)
双精度(位)
带偏阶的指数表示法
IEEE754标准规定单精度的偏阶为127(01111111,27-1),双精度的偏阶为1023(0111……11,210-1)
所以,
单精度的表示范围为
+/- 1.0000 0000 0000 0000 0000 000 * 2-126(指数全零表示0或者非规格数)
到
+/- 1.0000 0000 0000 0000 0000 000 * 2-127(指数全1表示无穷或者NaN)
双精度的表示范围为
+/- 1.00……0 * 2-1022(指数全零表示0或者非规格数)
到
+/- 1.00……0 * 2-1023(指数全1表示无穷或者NaN)
提问:IEEE 754标准中,阶的偏置值为什么是127,而不是128?
为了让表示的范围能够对称起来
当阶码E 为全0且尾数M 也为全0时,表示的真值x 为零,结合符号位S 为0或1,有正零和负零之分。当阶码E 为全1且尾数M为全0时,表示的真值x 为无穷大,结合符号位S 为0或1,也有+∞和-∞之分。这样在32位浮点数表示中,要除去E,用全0和全1(255)10表示零和无穷大的特殊情况,指数的偏移值不选128(10000000),而127(01111111)。对于规格化浮点数,阶码E范围是1~254。
分两种情况计算如下:
1)偏移值为127时,绝对值范围大致是:1.2*10^(-38)~3.4*10^(+38);
2)如果偏移值取为128时, 绝对值范围大致是:5.9*10^(-39)~1.7*10^(+38);
可见偏移值取127时,上下范围基本对称,相对合理点。
或者也可以这么理解: 由于8位E中,只有7位有效数字,7位能表示的大小为0-127,所以偏移量可以在0-127中任取一值,在IEEE754Z中规定取127.
非规格数
先来看看非规格化数值的的表示形式与规格数的表示形式相一致,但是计算的数值会有所差异,
(-1)S * F * 2E
指数域为全零,实际的指数值E=1-bias,而有效数值M=F(而不是规格数中的M=1+F)
为什么非规格化的值的指数值为1-bias而不是-bias?
这种方式提供了一种从非规格方式值平滑转换到规格化值的办法。 ——《深入理解计算机系统》
![]()
但是这种平滑处理与“IEEE 754标准中,阶的偏置值为什么是127,而不是128?”关系不大,因为即使阶的偏置值是128一样可以实现非规格数向规格数的平滑转变(此时,最大非规格数为7/1024, 最小规格数为8/1024)。因此,“非规格数向规格数的平滑转变”归功于“非规格化的值的指数值为1-bias而不是-bias”,而与IEEE754标准阶的偏置值是127还是128关系不大。
为什么要设置非规格数呢?
一是为了提供一种表示0的方法,因为使用规格数,有效数值为M>=1,这样就无法表示零。实际上,+0.0的浮点表示的位模式为全0,-0.0的浮点表示的位模式:符号位为1,其余位均为0.尽管正负零会有差异之处。
二是用来表示那些非常接近0.0的数。它们提供了一种属性,称为“逐渐溢出”(gradual underflow).
非规格化浮点数在允许浮点误差的前提下,可以使任何浮点运算可以在任何浮点数上操作,而不产生下溢出异常,但另一方面它也可能导致更多的除以0错误和NaN的出现。Consider the different numbers
A: 0 00000009 10010101111001111111111
B: 0 00000009 10010101111100001010000
They are valid floating point members, very small but still finite. But as you see the first 11 bits are identical. If you now subtract A-B or B-A the first valid bit leaves the lower exponent range, so the result without gradual underflow is….0. So A != B but A-B = 0.
IEEE754浮点数编码
指数有k位,尾数n位,则偏阶(bias)为2k-1-1
概述 | 指数 | 小数 | 单精度 | 双精度 |
---|---|---|---|---|
0 | 00……00 | 00……00 | 0 | 0 |
最小非规格数 | 00……00 | 00……01 | 2-23*2-126 | 2-52*2-1022 |
最大非规格数 | 00……00 | 11……11 | (1-2-23)*2-126 | (1-2-52)*2-1022 |
最小规格数 | 00……01 | 00……00 | 1*2-126 | 1*2-1022 |
1 | 01……11 | 00……00 | 1 | 1 |
最大规格数 | 11……10 | 11……11 | (2-2-23)*2127 | (2-2-52)*21023 |
浮点运算
加法
步骤:
较小指数向较大指数对齐
有效数字相加
规格化(检查上溢或者下溢)
四舍五入
示例
Example addition in binary
Perform 0.5 + (-0.4375):
0.5 = 0.1 × 20 = 1.000 × 2-1 (normalised)
-0.4375 = -0.0111 × 20 = -1.110 × 2-2 (normalised)
Rewrite the smaller number such that its exponent matches with the exponent of the larger number.
-1.110 × 2-2 = -0.1110 × 2-1
Add the mantissas:
1.000 × 2-1 + -0.1110 × 2-1 = 0.001 × 2-1
Normalise the sum, checking for overflow/underflow:
0.001 × 2-1 = 1.000 × 2-4
-126 <= -4 <= 127 ===> No overflow or underflow
Round the sum:
The sum fits in 4 bits so rounding is not required
Check: 1.000 × 2-4 = 0.0625 which is equal to 0.5 - 0.4375
Correct!
乘法
步骤:
计算新的指数
有效数字相乘,并确定小数点位置
规格化(检查上溢或者下溢)
四舍五入
确定符号:源操作数符号相异,符号位为1,否则为0
示例:
Example multiplication in binary:
1.000 × 2-1 × -1.110 × 2-2
Add the biased exponents
(-1 + 127) + (-2 + 127) - 127 = 124 ===> (-3 + 127)
Multiply the mantissas
The product is 1.110000 × 2-3
Need to keep it to 4 bits 1.110 × 2-3
Normalise (already normalised)
At this step check for overflow/underflow by making sure that
-126 <= Exponent <= 127
1 <= Biased Exponent <= 254
Round the result (no change)
Adjust the sign.
Since the original signs are different, the result will be negative -1.110 × 2-3