计算机组成原理——第二章(18)

本小节我们讲一下阶码和尾数,同时还有原码和补码规格化(左归、右归)

浮点数的表示

1.表示

阶码+尾数

例如普通的计数法:+302657264526,用科学计数法表示就是+3.026*10^{11},而其实对于科学计数法,可以把10省略掉,就可以这样书写,+11+3.026,这就是阶码和尾数

+11+3.026+就是阶符,11就是阶码的数值部分,+是数符,3.026是尾数的数值部分,可以看到尾数的数值部分越短的话,能表示的精度就越低

阶码:常用补码或移码表示的定点整数

尾数:常用原码或补码表示的定点小数

阶码E反应浮点数的表示范围及小数点的实际位置,尾数M的数值部分的位数n反应浮点数的精度

 a:阶码0,01对应真值+1

        尾数1.1001因为是补码表示,对应真值-0.0111

a的真值=2^{1}*(-0.0111)=-0.111,如果是1B的存储空间,刚好存放这么多数字

 b:阶码0,10对应真值+2

        尾数0.01001对应真值+0.01001=+(2^{-2}+2^{-5}

那么b的真值=2^2*(+0.01001)=+1.001,要存储在1B的存储空间,那么就会发生移除

为了解决这个问题,我们可以将阶码-1得到1,尾数往左移,得到0.1001 ,这样1B就可以存得下了

上面方法把尾数左移,阶码-1,这个方法我们叫做左归 ,接下来我们还会讲右归

2.规格化

2.1尾数最高位

规格化浮点数:规定尾数的最高数值位必须是一个有效值

2.2左归

当浮点数运算的结果为非规格化的要进行规格化处理,将尾数算数左移一位,阶码-1

2.3右归

当浮点数运算的结果尾数出现溢出(双符号位为10或10时),将尾数算数右移一位,阶码+1

 

注意:采用“双符号位”,当溢出发生时,可以挽救,更高的符号位是正确的符号位 

2.4原码表示的尾数规格化

原码表示比较简单,同学们只需要记住,不管正数还是负数,最高位都是1,然后表示范围相信同学们临时也可以算出来

2.5补码表示的尾数规格化

补码的正数和负数尾数规格化,同学需要记住,符号位和最高位相反就行了!!

而且尾数的表示范围,记得需要把补码转成原码,我看课的时候,好多弹幕在说,为什么负数尾数的最小值是-1,1.00..0是怎么转成-1的,要知道原码转补码有两种方法,一种是找到最右边的1法;另一种是数值位全部取反,末位+1,这样1.00...0转原码就是-1,而且格外注意,补码的最小范围是比原码的最小范围小1的,忘记的同学可以看一下这个文章

 

 我们知道补码尾数的规格化要保证符号位与最高位相反,所以我们将1.1110100左移3位,得到1.0100000,同时阶码-3,0.110-3=0.011,这就是补码规格化

3.表示范围

表示范围考研大纲剔除了,所以我们就了解一下

正上溢:超出了正数所能表示的最大范围 

正下溢:超出了正数所能表示的最小范围 

负上溢:超出了负数所能表示的最小范围 

负下溢:超出了负数所能表示的最大范围 

遇到负下溢或者正下溢的时候通常当做0,当负上溢或者正上溢的时候,通常爆出异常

3.思维导图

好的,这个问题需要一些数学和编程的知识。我会尽力回答你的问题,但是由于篇幅限制,可能无法讲得十分详细。如果你有具体的问题或者不理解的地方,可以继续问我。 首先,我们需要了解二进制浮点数的存储格式。在IEEE 754标准中,一个二进制浮点数由三部分组成:符号位、阶码和尾数。其中符号位用来表示正负,阶码用来表示指数,尾数用来表示有效数字。 在单精度浮点数中,符号位占1位,阶码占8位,尾数占23位。在双精度浮点数中,符号位占1位,阶码占11位,尾数占52位。这里我们假设输入的是单精度浮点数。 接下来,我们需要了解浮点数加减法的实现原理。浮点数的加减法与十进制数的加减法类似,需要先对阶,然后进行尾数的加减,最后将结果规格化。具体实现过程可以参考下面的代码。 ```python def float_add_sub(a, b, op): # 将a, b转换成二进制浮点数表示 sa, ea, ma = float_to_binary(a) sb, eb, mb = float_to_binary(b) # 对阶 if ea < eb: ea, eb = eb, ea ma, mb = mb, ma sa, sb = sb, sa shift = ea - eb mb = (1 << 23) | mb # 补上隐藏的1 mb = mb >> shift # 右移 eb = ea # 尾数的加减 if op == '+': m = ma + mb else: m = ma - mb if m == 0: return (0, 0, 0) # 结果为0 while m >> 23 == 0: m = m << 1 eb -= 1 if m >> 24 == 1: m = m >> 1 eb += 1 # 转换成二进制浮点数表示 s = sa e = eb - 127 m = m & 0x7fffff return (s, e, m) def float_to_binary(f): s = 0 if f >= 0 else 1 f = abs(f) e = 0 while f >= 2: f /= 2 e += 1 while f < 1: f *= 2 e -= 1 m = int((f - 1) * (1 << 23)) return (s, e + 127, m) ``` 这个函数可以实现浮点数的加减法,其中参数a和b分别表示要进行加减的两个浮点数,op表示要进行的操作,可以取'+'或'-'。函数返回一个三元组(s, e, m),分别表示符号位、阶码和尾数。 接下来,我们可以根据这个函数编写GUI程序,具体代码如下: ```python import tkinter as tk def float_to_str(s, e, m): if s == 1: sign = '-' else: sign = '+' if e == 0: exp = '00000000' else: e += 127 exp = bin(e)[2:].zfill(8) frac = bin(m)[2:].zfill(23) return sign + exp + frac def str_to_float(s): if s[0] == '-': sign = 1 else: sign = 0 e = int(s[1:9], 2) - 127 m = int(s[9:], 2) return sign, e, m def float_add_sub_gui(): def calculate(): a = float(entry1.get() + entry2.get()) b = float(entry3.get() + entry4.get()) if op.get() == '+': s, e, m = float_add_sub(a, b, '+') entry5.delete(0, tk.END) entry6.delete(0, tk.END) entry5.insert(0, str(e)) entry6.insert(0, float_to_str(s, e, m)) else: s, e, m = float_add_sub(a, b, '-') entry7.delete(0, tk.END) entry8.delete(0, tk.END) entry7.insert(0, str(e)) entry8.insert(0, float_to_str(s, e, m)) root = tk.Tk() root.title('浮点数加减法') label1 = tk.Label(root, text='阶码1:') label1.grid(row=0, column=0) entry1 = tk.Entry(root) entry1.grid(row=0, column=1) label2 = tk.Label(root, text='尾数1:') label2.grid(row=0, column=2) entry2 = tk.Entry(root) entry2.grid(row=0, column=3) label3 = tk.Label(root, text='阶码2:') label3.grid(row=1, column=0) entry3 = tk.Entry(root) entry3.grid(row=1, column=1) label4 = tk.Label(root, text='尾数2:') label4.grid(row=1, column=2) entry4 = tk.Entry(root) entry4.grid(row=1, column=3) op = tk.StringVar() op.set('+') radio1 = tk.Radiobutton(root, text='加法', variable=op, value='+') radio1.grid(row=2, column=0) radio2 = tk.Radiobutton(root, text='减法', variable=op, value='-') radio2.grid(row=2, column=1) button = tk.Button(root, text='计算', command=calculate) button.grid(row=2, column=3) label5 = tk.Label(root, text='阶码:') label5.grid(row=3, column=0) entry5 = tk.Entry(root) entry5.grid(row=3, column=1) label6 = tk.Label(root, text='尾数:') label6.grid(row=3, column=2) entry6 = tk.Entry(root) entry6.grid(row=3, column=3) label7 = tk.Label(root, text='阶码:') label7.grid(row=4, column=0) entry7 = tk.Entry(root) entry7.grid(row=4, column=1) label8 = tk.Label(root, text='尾数:') label8.grid(row=4, column=2) entry8 = tk.Entry(root) entry8.grid(row=4, column=3) root.mainloop() if __name__ == '__main__': float_add_sub_gui() ``` 这个程序使用了tkinter模块实现了GUI界面,可以方便地进行输入和输出。需要注意的是,输入的阶码和尾数需要进行字符串转换,输出的阶码和尾数需要进行二进制转换。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值