csapp_ch2_信息的表示和处理

本章重要的知识点:

  • 三种重要的数字编码表示
    • 无符号编码
    • 补码编码
    • 浮点数编码
  • 整数的表示虽然只能编码较小的范围,但却是精确的,而浮点数虽然可以编码较大的数值范围,但这种表示是近似的
  • 字节顺序,大端vs小端
  • 强制类型转换,底层的位值是不变的,只是改变了解释这些位的方式
  • 两个正数相加会得出一个负数,而比较表达式x<yx-y<0会产生不同的结果,这是因为算术运算可能会溢出
  • 补码非的两种方法
  • IEEE浮点数表示,int类型的12345与float类型12345.0的二进制表示之间的关联

1 字节顺序之大端与小端的区别

什么是字节顺序?

对于单字节的对象,没有字节顺序,因为无论怎么存储都是一个顺序,比如char。对于多字节对象,要保存在内存中,我们需要考虑在内存中如何排列这些字节,并且这些字节的地址是什么?

我们来看下大端和小端的定义:

  • 大端:内存地址由低到高,内存按照由最高有效字节到最低有效字节的顺序存储对象。
  • 小端:内存地址由低到高,内存按照由最低有效字节到最高有效字节的顺序存储对象。

假如有一个int类型的变量为0x01234567,位于地址0x100处,那么存储的地址范围为0x100~0x103,大端和小端的表示方法如下:

image-20210428152521183

其中0x01234567高位字节0x01低位字节0x67

为什么会有小端字节序呢?

计算机电路先处理低位字节,效率比较高。因为计算都是从低位开始的,所以,许多计算机内部采用小端字节序。但人类习惯大端字节序。比如网络传输和文件存储就是大端字节序。

2 计算补码非的两种方法

第一种就是常见的取反加一。对每一位求补,再对结果加一。比如整数值x,计算表达式-x~x+1的结果是一样的。在读csapp的时候发现了比较有意思的另外一种方法,首先将x的二进制表示处理,从右到左←的方向,找到第一个的1,然后再将这个1左边的位取反,就得到-x一样的结果。

例子如下:

第一种方法

image-20210428155322620

第二种方法

image-20210428155335855

3 IEEE浮点表示方法

我们先来看一个有意思的现象,int类型的12345和float类型的12345.0,它们的十六进制表示分别为0x000030390x4640e400

image-20210428160429982

如图,它们对应的二进制用红色的方框圈出来的部分相同,这是为什么呢?学习了IEEE浮点表示方法,你就知道了。

IEEE浮点方法用下面的公式来表示一个数:
V = ( − 1 ) s × M × 2 E V = (−1)^s × M × 2^E V=(1)s×M×2E

  • s,sign表示符号位,决定V是整数还是负数,0为正,1为负。

    • 一个单独的符号位s直接编码符号s
  • M,表示尾数,是一个二进制小数。

    • n位小数字段frac编码尾数M,但编码出来的值还需要根据阶码字段的值是否等于0
       frac  = f n − 1 ⋯ f 1 f 0 \text { frac }=f_{n-1} \cdots f_{1} f_{0}  frac =fn1f1f0
  • E,exponent表示阶码,也就是指数部分。

    • k位的阶码字段exp编码阶码E
      exp ⁡ = e k − 1 ⋯ e 1 e 0 \exp =e_{k-1} \cdots e_{1} e_{0} exp=ek1e1e0

单精度浮点格式(32位),s、exp和frac字段分别为1位、8位和23位。而双精度浮点格式(64位),s、exp和frac字段分别为1位、11位和52位。

image-20210428162419564

根据exp的值,将被编码的值分为三种不同的情况(以32位为例):

image-20210428162920616

  1. 规格化的值

这是最常见的情况,exp的值不为0和255。在这种情况中,阶码的值E需要以偏置的形式来表示。
E = e − Bias ⁡ E=e-\operatorname{Bias} E=eBias

B i a s = 2 k − 1 − 1 Bias=2^{k-1}-1 Bias=2k11

在单精度中k为8,Bias为127。

小数字段frac用来表示小数值f。尾数定义为:
M = 1 + f M=1+f M=1+f

  1. 非规格化的值

当exp为0时,则为非规格化的值。在这种情况下,阶码值和尾数值如下:
E = 1 − Bias ⁡ E=1-\operatorname{Bias} E=1Bias

M = f M=f M=f

  1. 特殊值(无穷大,NaN)

当阶码值全为1时,小数域全为0表示无穷大,小数域为非零时,结果值为NaN(不是一个数的缩写)。

有了以上的理论,我们就可以尝试将整数值12345转换为浮点数12345.0(float类型)。12345的二进制表示为[11000000111001],将其转换为IEEE浮点格式
V = ( − 1 ) s × M × 2 E V=(-1)^{s} \times M \times 2^{E} V=(1)s×M×2E
[11000000111001]的二进制小数点左移动13位,创建12345的规格化表示:
12 , 345 = 1.100000011100 1 2 × 2 13 12,345=1.1000000111001_{2} \times 2^{13} 12,345=1.10000001110012×213

  • 构造小数字段frac,丢弃开头的1,此时小数点后面有13位,因为frac一共有23位,所以需要在末尾增加10个0,从而生成frac字段[110000001110010000000000]
  • 构造阶码E,因为是规格化的值,E=e-Bias,故e=E+Bias=13+127=140,其二进制为[10001100]
  • 符号位,正数为0。

因此,我们就得到了12345.0的二进制浮点数表示[010001100110000001110010000000000]12345的二进制整数表示为

[00000000000000000011000000111001]。到此,我们就可以解释为什么1234512345.0的二进制表示有部分是相同的,示意图如下:

image-20210428170746069

参考:Computer Systems A Programmer’s Perspective THIRD EDITION

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值