硬件中的数

硬件中的数

一、整数

1.1 二进制数与十进制数间的转换

​ 首先强调,这里的二进制数是补码形式的(这里的补码就是负数补码,正数原码),我后面进行数学推导的时候,用的是n位的二进制数,从高到低,分别是 a n − 1 , a n − 2 , ⋅ ⋅ ⋅ , a 0 a_{n-1},a_{n-2},\cdot\cdot\cdot,a_0 an1,an2,,a0

​ 对于二进制转十进制,有公式
d e c i m a l = − a n − 1 ∗ 2 n − 1 + a n − 2 ∗ 2 n − 2 + ⋅ ⋅ ⋅ + a 0 ∗ 2 0 decimal = -a_{n-1}*2^{n-1} + a_{n-2}*2^{n-2}+\cdot\cdot\cdot+a_0*2^0 decimal=an12n1+an22n2++a020
​ 这是因为补码的本质是将一个负数用一个正数表示,补码的构造是结合溢出,也就是取余操作,比如对于四位二进制,-4对应的是

12,也就是 − 4 + 2 4 = 12 -4+2^4 = 12 4+24=12,可以看出,如果想把补码(负数对应的正数)还原成原来的负数,需要减去 2 n 2^n 2n ,所以对于一个二进制数表示的负数,如果按照无符号的算法,有usigned_decimal,减去 2 n 2^n 2n,就得到了signed_decimal
u n s i g n e d _ d e c i m a l = a n − 1 ∗ 2 n − 1 + a n − 2 ∗ 2 n − 2 + ⋅ ⋅ ⋅ + a 0 ∗ 2 0 unsigned \_decimal = a_{n-1}*2^{n-1} + a_{n-2}*2^{n-2}+\cdot\cdot\cdot+a_0*2^0 unsigned_decimal=an12n1+an22n2++a020
s i g n e d _ d e c i m a l = u n s i g n e d _ d e c i m a l − 2 n = − a n − 1 ∗ 2 n − 1 + a n − 2 ∗ 2 n − 2 + ⋅ ⋅ ⋅ + a 0 ∗ 2 0 signed \_decimal =unsigned \_decimal-2^n= -a_{n-1}*2^{n-1} + a_{n-2}*2^{n-2}+\cdot\cdot\cdot+a_0*2^0 signed_decimal=unsigned_decimal2n=an12n1+an22n2++a020

​ 然后发现,对于二进制正数,上面的计算公式也恰巧符合 a n − 1 a_{n-1} an1 恰好为0,正负不影响),所以这个公式就很简便了。

​ 对于十进制转二进制,对于正数,就可以直接转化,对于负数 x 0 x_0 x0 ,需要先写出其绝对值的二进制表示 x 1 x_1 x1 ,在逐位取反得到 x 2 x_2 x2 ,然后加一,就可以得到对应的二进制数 x 3 x_3 x3 ,现在我们来证明这个操作的合法性。有公式
x 1 = − x 0 x_1 = -x_0 x1=x0
x 1 + x 2 = 111 ⋅ ⋅ ⋅ 1 = 2 n − 1 x_1 + x_2 = 111\cdot\cdot\cdot1 = 2^n - 1 x1+x2=1111=2n1
x 2 = 2 n − 1 − x 1 x_2 = 2^n-1-x_1 x2=2n1x1
​ 此时如果我们再给 x 2 x_2 x2 加 1 ,就得到了式子
x 3 = 2 n − x 1 = 2 n + x 0 x_3 = 2^n - x_1 = 2^n + x_0 x3=2nx1=2n+x0
​ 依照溢出原理,一个负数加上 2 n 2^n 2n,就可以得到对应的正数。所以 x 3 x_3 x3 就是 x 1 x_1 x1 对应的那个正数。

1.2 通用加法器的实现

​ 对于正数,就是以原码的形式储存,对于负数,是按照补码的形式存储的,这是补码的第一次应用,这样存储的好处是可以将原来以无符号加法为实现目标的加法器,也可以用于**“负数 + 正数”、“正数 + 负数”、“负数 + 负数” **的通用加法器,不需要更改一点硬件设计,这是因为有如下公式
计 算 机 中 负 数 + 正 数 = 实 际 负 数 + 2 n + 正 数 = 实 际 负 数 + 正 数 ( 利 用 溢 出 原 理 消 去 2 n ) 计算机中负数 + 正数 = 实际负数 + 2^n + 正数 = 实际负数 + 正数(利用溢出原理消去2^n) +=+2n+=+2n
计 算 机 中 负 数 1 + 计 算 机 中 负 数 2 = 实 际 负 数 1 + 2 n + 实 际 负 数 2 + 2 n = 实 际 负 数 1 + 实 际 负 数 2 计算机中负数1 + 计算机中负数2 = 实际负数1 + 2^n + 实际负数2 + 2^n = 实际负数1 + 实际负数2 1+2=1+2n+2+2n=1+2

1.3 减法器的实现

​ 这是补码的第二次应用,这次跟通用加法器的实现不同,是需要更改一些硬件基础的,对于减数,需要在前面增加一个n位的异或门,一个n位输入接减数,另一个接减法信号(sub == 1时,实现减法器功能,sub == 0 时,实现加法器功能)。此外,还需要把加法器的进位输入端连接到减法信号,整体的效果当要进行减法的时候,是对于减数进行取反操作,并给结果加1,可以知道,这样构造出的减法器应用了补码原理,而且是通用减法器

​ 硬件描述如下:

module Adder_subtractor(input [15:0] a, input [15:0] b, input sub, output [15:0] ans);
    wire carry;
    wire [15:0] tmp = b ^ {16{sub}};//如果sub == 1,就对b取反,如果 sub == 0,就不发生变化
    
    add16 sub(a, tmp, sub, ans, carry);//大部分硬件还是与加法器上搭建的

endmodule

module add16(input [15:0] a, input [15:0] b, input cin, output [15:0] sum, output cout);
	
	assign {cout, sum} = a + b;
	
endmodule

1.4 位数拓展

​ 比如要把一个 4 位的二进制数拓展成 8 位,还不能改变他所代表的值。可以这么做,将 a n − 1 a_{n-1} an1 复制到待扩展位中,就可以满足条件。我们采用迭代证明,对于n位数,如果扩展到n+1可以,那么扩展到n+2,n+3,n+4……都可以。

​ 对于正数,前面添一个0,显然对值本身不会造成任何影响,对于负数,前面添一个1,我们将其转换为十进制
e x t e n d = − a n ∗ 2 n + a n − 1 ∗ 2 n − 1 + ⋅ ⋅ ⋅ + a 0 ∗ 2 0 extend =-a_{n}*2^{n} + a_{n-1}*2^{n-1}+\cdot\cdot\cdot+a_0*2^0 extend=an2n+an12n1++a020
​ 我们又有:
a n = 1 , a n − 1 = 1 a_n= 1, a_{n-1} = 1 an=1an1=1
​ 所以有
e x t e n d = − a n ∗ 2 n + a n − 1 ∗ 2 n − 1 + ⋅ ⋅ ⋅ + a 0 ∗ 2 0 = − a n − 1 ∗ 2 n − 1 + a n − 2 ∗ 2 n − 2 + ⋅ ⋅ ⋅ + a 0 ∗ 2 0 = n o n _ e x t e n d extend =-a_{n}*2^{n} + a_{n-1}*2^{n-1}+\cdot\cdot\cdot+a_0*2^0 =-a_{n-1}*2^{n-1} + a_{n-2}*2^{n-2}+\cdot\cdot\cdot+a_0*2^0 = non\_extend extend=an2n+an12n1++a020=an12n1+an22n2++a020=non_extend

1.5 溢出判断

​ 溢出有两种形式,“正数+正数”和“负数+负数”(减法自动转化)。最简单的方法是判断最高位的进位carry_out次高位的进位carry_out是否相同,如果相同,就说明发出了溢出。

​ 对于**“正数+正数”**,显然最高位肯定carry_out是0(两个0和一个carry_in相加没办法进位)如果被次高位进位了,那么它就变成了一个负数了,所以要求次高位不能进位。

​ 对于**“负数+负数”**,最高位的carry_out一定是1,如果是次高位没有1进上来,那么就会在最高位出现0,就溢出了,如果是进上来了,那么可以证明结果尽管发出了物理上的溢出,但是在数值上没有问题,因为有公式
计 算 机 中 负 数 1 + 计 算 机 中 负 数 2 = 实 际 负 数 1 + 2 n + 实 际 负 数 2 + 2 n 计算机中负数1 + 计算机中负数2 = 实际负数1 + 2^n + 实际负数2 + 2^n 1+2=1+2n+2+2n
​ 对于溢出,其实就是减掉一个 2 n 2^n 2n​​,显然是不会对真值造成影响的。

1.6 超前进位加法器

C1 = A0 & B0 | C0 & (A0 ^ B0);
C2 = A1 & B1 | C1 & (A1 ^ B1);
...
Cn = An-1 & Bn-1 | Cn-1 & (An-1 ^ Bn-1);

//所以如果我们这样转换变量
Gi = Ai & Bi; Pi = Ai ^ Bi;
//就会有如下式子
C1 = G0 | P0 & c0;
C2 = G1 | G0 & P1 | P0 & P1 & C0;
C3 = G2 | G1 & P2 | G0 & P1 & P2 | P0 & P1 & P2 & C0;
C4 = G3 | G2 & P3 | G1 & P2 & P3 | G0 & P1 & P2 & P3 | P0 & P1 & P2 & P3 & C0;

​ 可以看到, C i C_i Ci 不再和 C i − 1 C_{i-1} Ci1 有直接关系了,这样就为并行计算提供了方法。但是相应的,电路设计变得复杂。


二、浮点数

2.1 最基础的浮点数表示

​ 我们用一个十进制数288来举例,288的二进制表示是11100100,转换为科学计数法就是 1.11001 ∗ 2 111 1.11001 * 2^{111} 1.110012111​ 。我们用符号位存储数的正负,用阶码存储基数的幂次,用尾数存储那个小数。

符号(1位)阶码(8位)尾数(23位)
00000_0111111_0010_0000_0000_0000_0000

2.2 隐含前导1

​ 我们注意到,只要需要存储的数字不是0,尾数的第一位就一定是1,所以就没有必要每次花一个数据位去保存了,所以我们就得到了采用隐含前导1的第二种表示方法。

符号(1位)阶码(8位)尾数(23位)
00000_0111110_0100_0000_0000_0000_0000

2.3 偏码与补码

​ 那么如果遇到阶码是负数的情况怎么办,当然我们可以用补码来表示,但是补码不太符合浮点数的计算要求,为什么这么说呢?首先我要了解一下浮点数的加法过程

​ 面对浮点数加法,我们与整数加法不同的是,我们要先比较阶码的大小,然后利用阶码的差,将尾数对齐,那么显然,补码的设计是不适合进行比较的,比如-1永远都对应最大的无符号数,比所有的正数都大。我们需要的是一个好比较的数制

​ 这是偏码的长处,偏码就是把原始阶码加上了一个常数偏置。这个常数一般是 2 n − 1 − 1 2^{n-1} - 1 2n11​ ,其中 n 是阶码的位数,这样一来,阶码的大小比较就很容易了,而且计算差值也不会受到影响。所以采用了偏码的288,储存形式如下:

符号(1位)阶码(8位)尾数(23位)
01000_0110110_0100_0000_0000_0000_0000

​ 那么为什么不所有的数都采用偏码表示,舍弃补码的用法,这可能是因为补码能更好的适应加减法吧。

2.4 浮点数的表示范围

​ 需要明确的一点,尽管浮点数的表示范围大了,但是其实他能表示的数还是 2 32 2^{32} 232 个,这跟一个int表示的数是一样的,准确的来说,是浮点数的上限高了,但是范围内只能表示特定的一些数。因为只有 2 32 2^{32} 232 中状态,所以只能表示 2 32 2^{32} 232 种数,这是很直白的道理。

​ 所以与浮点数相伴随的,是舍入现象和溢出现象,因为没办法精确表示每一个数,所以舍入是必然的。溢出也比整型要复杂,分为负上溢出(负数太小了),负下溢出(负数太接近0了),正下溢出(正数太接近0了),正上溢出(正数太大了)。

2.5 特殊情况的表示

​ 正如2.4节形容的,有些数是没有办法按常理表示的,所以我们分出了几个状态来表示这些特殊值

数字符号阶码小数
0x0000_0000000_0000_0000_0000_0000_0000
$\infty $01111_1111000_0000_0000_0000_0000_0000
− ∞ -\infty 11111_1111000_0000_0000_0000_0000_0000
NaNx1111_1111非零

2.6 IEEE 754 标准

​ 采用隐含前导1,偏码,特殊情况的数制就是这个标准。


三、位,字节,字

3.1 位(bit)

​ 位是存储最小单位,就是0或者1的感觉。

3.2 字节(byte)

​ 字节是计算机数据处理的基本单位,一般用大写的B来表示

3.3 字(word)

Buses are typically designed to transfer fixed-sized chunks of bytes known as words. The number of bytes in a word(the word size) is a fundamental system parameter that varies across systems. Most machines today have sizes of either 4 bytes(32 bits) or 8 bytes(64 bits)

​ 也就是说,字跟数据处理没有关系,它是形容总线传输能力的参数,因为总线与CPU联系紧密,所以字也可被视作CPU一次处理数据的最大量,总的来说,是硬件参数。平常说的64位电脑,就是说最大可以处理64bit的数据,所以 1 w o r d = 64 b i t = 8 b y t e 1 word = 64 bit = 8 byte 1word=64bit=8byte

  • 6
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值