深入理解计算机系统(2):信息的表示和处理

信息存储

大多数计算机使用 8 位的块,或者字节(byte),作为最小的可寻址的内存单位,而不是访问内存中单独的位。机器级程序将内存视为一个非常大的字节数组,称为虚拟内存(virtual memory)。内存的每个字节都由一个唯一的数字来标识,称为它的地址(address),所有可能地址的集合就称为虚拟地址空间(virtual address space)。顾名思义,这个虚拟地址空间只是一个展现给机器级程序的概念性映像。

编译器和运行时系统将存储器空间划分为更可管理的单元,来存放不同的程序对象(program object),即程序数据、指令和控制信息可以用各种机制来分配和管理程序不同部分的存储。这种管理完全是在虚拟地址空间里完成的。

十六进制表示法

二进制表示法太冗长,而十进制表示法与位模式的互相转化很麻烦。替代的方法是,以16 为基数,或者叫做 十六进制(hexadecimal) 数,来表示位模式。十六进制(简写为“hex”)使用数字 ‘0’ ~ ‘9’ 以及字符’A’ ~ ‘F’来表示 16 个可能的值。
在这里插入图片描述
C,C++ 种以 0x0X 开头的数字常量被认为是十六进制的值。 十六进制不区分大小写

字数据大小

每台计算机都有一个字长(word size),指明指针数据的标称大小(nominalsize)
因为虚拟地址是以这样的一个字来编码的,所以字长决定的最重要的系统参数就是虚拟地址空间的最大大小。也就是说,对于一个字长为 w w w 位的机器而言,虚拟地址的范围为 0   2 w − 1 0~2^w-1 0 2w1,程序最多访问 2 w 2^w 2w 个字节。
32 位字长限制虚拟地址空间为 4 千兆字节(写作 4GB),刚刚超过 4 × 1 0 9 4 \times 10^9 4×109 字节。扩展到 64 位字长使得虚拟地址空间为 16EB,大约是 1.84 × 1 0 19 1.84 \times 10^{19} 1.84×1019 字节。

大多数 64 位机器也可以运行为 32 位机器编译的程序,这是一种向后兼容。
该程序就可以在32 位或64 位机器上正确运行
程序用下述伪指令编译:

linux> gcc -m32 xxx.c
linux> gcc -m64 xaxx.c

C 语言各种数据类型分配的字节数:
在这里插入图片描述
C/C++ 语言中,下列声明都是一个意思:

unsigned long
unsigned long int
long unsigned
long unsigned int

寻址和字节顺序

对于跨越多字节的程序对象,必须建立两个规则:这个对象的地址是什么,以及在内存中如何排列这些字节。
在几乎所有的机器上,多字节对象都被存储为连续的字节序列,对象的地址为所使用字节中最小的地址

排列表示一个对象的字节有两个通用的规则。考虑一个 w w w 位的整数,其位表示为 [ x w − 1 , z w − 2 , . . . , x 1 , x 0 ] [x_{w-1},z_{w-2},...,x_1,x_0] [xw1,zw2,...,x1,x0],其中 x w − 1 x_{w-1} xw1 是最高有效位,而 0 是最低有效位。
假设 w w w 是8 的倍数,这些位就能被分组成为字节,其中最高有效字节包含位 [ x w − 1 , z w − 2 , . . . , x w − 8 ] [x_{w-1},z_{w-2},...,x_{w-8}] [xw1,zw2,...,xw8],而最低有效字节包含位 [ x 7 , z 6 , . . . , x 0 ] [x_{7},z_{6},...,x_{0}] [x7,z6,...,x0],其他字节包含中间的位。
某些机器选择在内存中按照从最低有效字节到最高有效字节的顺序存储对象,而另一些机器则按照从最高有效字节到最低有效字节的顺序存储。前一种规则一一最低有效字节在最前面的方式,称为小端法(little endian),后一种规则——最高有效字节在最前面的方式,称为大端法(big endian)
许多比较新的微处理器是 双端法(bi-endian) ,也就是说可以把它们配置成作为大端或者小端的机器运行。然而,实际情况是:一旦选择了特定操作系统,那么字节顺序也就固定下来。

表示字符串

C 语言中字符串被编码为一个以 null (其值为 0) 字符结尾的字符数组。每个字符都由某个标准编码来表示,最常见的是 ASCII 字符码。
在使用 ASCII码作为字符码的任何系统上都将得到相同的结果,与字节顺序和字大小规则无关。因而,文本数据比二进制数据具有更强的平台独立性。
ASCII 字符集适合于编码英语文档,但是在表达一些特殊字符方面并没有太多办法。
基本编码,称为 Unicode 的“统一字符集”,使用 32 位来表示字符。这好像要求文本串中每个字符要占用 4 个字节。不过,可以有一些替代编码,常见的字符只需要 1个或 2 个字节,而不太常用的字符需要多一些的字节数。
特别地,UTF-8 表示将每个字符编码为一个字节序列,这样标准 ASCII 字符还是使用和它们在 ASCII 中一样的单字节编码,这也就意味着所有的 ASCII 字节序列用 ASCII 码表示和用 UTF-8 表示是一样的。

表示代码

不同的机器类型使用不同的且不兼容的指令和编码方式。即使是完全一样的进程,运行在不同的操作系统上也会有不同的编码规则,因此二进制代码是不兼容的。
二进制代码很少能在不同机器和操作系统组合之间移植。

布尔代数简介

将逻辑值 TRUE(真)FALSE(假)编码为二进制值 10
在这里插入图片描述
布尔代数的运算。二进制值 10 表示逻辑值TRUE或者 FALSE,而运算符~&|^ 分别表示逻辑运算 NOTANDOREXCLUSIVE-OR

C 语言中的位级运算

在布尔运算中使用的那些符号就是 C语言所使用的:| 就是 OR(或)& 就是 AND(与)~ 就是 NOT(取反),而 ^ 就是 EXCLUSIVE-OR(异或)。这些运算能运用到任何“整型”的数据类型上,
在这里插入图片描述

C 语言中的逻辑运算

C 语言提供了一组逻辑运算符||&&!,分别对应于命题逻辑中的 ORANDNOT 运算。
逻辑运算很容易和位级运算相混淆,但是它们的功能是完全不同的。
逻辑运算认为所有非零的参数都表示 TRUE,而参数 0 表示 FALSE。它们返回 1 或者 0,分别表示结果为 TRUE 或者为 FALSE

C 语言中的移位运算

C语言提供了一组移位运算,向左或者向右移动位模式。
对于一个位表示为 [ x w − 1 , x w − 2 , . . . , x 0 ] [x_{w-1},x_{w-2},...,x_0] [xw1,xw2,...,x0] 的操作数 x x x,C 表达式 x<<k 会生成一个值,其位表示为 [ x w − k − 1 , x w − k − 2 , . . . , x 0 , 0 , . . . , 0 ] [x_{w-k-1},x_{w-k-2},...,x_0,0,...,0] [xwk1,xwk2,...,x0,0,...,0]。也就是说, x x x 向左移动 k k k 位,丢弃最高的 k k k 位,并在右端补 k k k0。移位量应该是一个 0   w − 1 0~ w-1 0 w1之间的值。移位运算是从左至右可结合的,所以 x << j << k 等价于(x << j) << k

有一个相应的右移运算 x>>k
逻辑右移在左端补 k k k0,得到的结果是 [ 0 , . . . , 0 , x w − 1 , x w − 2 , . . . , x k ] [0,...,0,x_{w-1},x_{w-2},...,x_k] [0,...,0,xw1,xw2,...,xk];
算术右移是在左端补个最高有效位的值,得到的结果是 [ x w − 1 , . . . , x w − 1 , x w − 1 , x w − 2 , . . . , x k ] [x_{w-1},...,x_{w-1},x_{w-1},x_{w-2},...,x_k] [xw1,...,xw1,xw1,xw2,...,xk]

在这里插入图片描述
斜体的数字表示的是最右端(左移)或最左端(右移)填充的值。可以看到除了一个条目之外,其他的都包含填充 0。唯一的例外是算术右移[10010101]的情况。因为操作数的最高位是 1,填充的值就是 1。

C 语言标准并没有明确定义对于有符号数应该使用哪种类型的右移一一算术右移或者逻辑右移都可以。不幸地,这就意味着任何假设一种或者另一种右移形式的代码都可能会遇到可移植性问题。然而,实际上,几乎所有的编译器/机器组合都对有符号数使用算术右移,且许多程序员也都假设机器会使用这种右移。另一方面,对于无符号数,右移必须是逻辑的

整数表示

整数数据类型

C 语言支持多种整型数据类型一一表示有限范围的整数。
每种类型都能用关键字来指定大小,这些关键字包括 char、short、long,同时还可以指示被表示的数字是非负数(声明为 unsigned),或者可能是负数(默认)。为这些不同的大小分配的字节数根据程序编译为 32 位还是 64 位而有所不同。根据字节分配,不同的大小所能表示的值的范围是不同的。
在这里插入图片描述一个很值得注意的特点是取值范围不是对称的一一负数的范围比整数的范围大 1。当我们考虑如何表示负数的时候,会看到为什么会这样。

C 语言标准定义了每种数据类型必须能够表示的最小的取值范围。
C 语言的整型数据类型的保证的取值范围。C语言标准要求这些数据类型必须至少具有这样的取值范围。
在这里插入图片描述

无符号数的编码

假设有一个整数数据类型有 w w w 位。我们可以将位向量写成 x ⃗ \vec x x ,表示整个向量,或者写 [ x w − 1 , x w − 2 , . . . , x 0 ] [x_{w-1},x_{w-2},...,x_0] [xw1,xw2,...,x0],表示向量中的每一位。把 x ⃗ \vec x x 看做一个二进制表示的数,就获得成 x ⃗ \vec x x 的无符号表示。
在这个编码中,每个位 x i x_i xi 都取值为 01,后一种取值意味着数值 2 i 2^i 2i 应为数字值的一部分。
用一个函数 B2U w \text{B2U}_w B2Uw(Binary to Unsigned 的缩写,长度为 w w w)来表示:
对向量 x ⃗ = [ x w − 1 , x w − 2 , . . . , x 0 ] \vec x =[x_{w-1},x_{w-2},...,x_0] x =[xw1,xw2,...,x0] B2U w ( x ⃗ ) = ∑ i = 0 w − 1 x i 2 i \text{B2U}_w(\vec x) = \sum_{i=0}^{w-1} x_i 2^i B2Uw(x )=i=0w1xi2i
函数 B2U w \text{B2U}_w B2Uw 将一个长度为 w w w 0 0 0 1 1 1 串映射到非负整数。
例如,$ B2U 4 ( [ 1011 ] ) = 1 ⋅ 2 3 + 0 ⋅ 2 2 + 1 ⋅ 2 1 + 1 ⋅ 2 0 ] 8 + 0 + 2 + 1 = 11 \text{B2U}_4([1011])=1 \cdot 2^3 + 0 \cdot 2^2 + 1 \cdot 2^1 + 1 \cdot 2^0 ] 8 + 0 +2 + 1 =11 B2U4([1011])=123+022+121+120]8+0+2+1=11
无符号数的二进制表示有一个很重要的属性,也就是每个介于 0   2 w − 1 0~2^w - 1 0 2w1 之间的数都有唯一一个 w w w 位的值编码。例如,十进制值 11 作为无符号数,只有一个 4 位的表示,即[1011].
函数 B2U w \text{B2U}_w B2Uw 是一个双射。

补码编码

对于许多应用,希望表示负数值。最常见的有符号数的计算机表示方式就是补码(two’s-complement)形式。在这个定义中,将字的最高有效位解释为负权(negativeweight)
用函数 B2T w \text{B2T}_w B2Tw (Binary to Two’s-complement 的缩写,长度为 w w w 来表示:
对向量 x ⃗ = [ x w − 1 , x w − 2 , . . . , x 0 ] \vec x =[x_{w-1},x_{w-2},...,x_0] x =[xw1,xw2,...,x0] B2T w = − x w − 1 2 w − 1 + ∑ i = 0 w − 2 x i 2 i \text{B2T}_w = -x_{w-1}2^{w-1}+\sum_{i=0}^{w-2}x_i 2^i B2Tw=xw12w1+i=0w2xi2i
最高有效位 x w − 1 x_{w-1} xw1 也称为符号位,它的“权重”为 − 2 w − 1 -2^{w-1} 2w1,是无符号表示中权重的负数。符号位被设置为 1 1 1 时,表示值为负,而当设置为 0 0 0 时,值为非负。
例如: B2T 4 ( [ 1011 ] = − 1 ⋅ 2 3 + 0 ⋅ 2 2 + 1 ⋅ 2 1 + 1 ⋅ 2 0 = − 8 + 0 + 2 + 1 = − 5 \text{B2T}_4([1011]=-1 \cdot 2^3+ 0 \cdot 2^2 + 1 \cdot 2^1 + 1 \cdot 2^0 =-8 + 0 + 2 + 1 = -5 B2T4[1011]=123+022+121+120=8+0+2+1=5

B2T w \text{B2T}_w B2Tw 是一个从长度为 w w w 的位模式到 TMin w \text{TMin}_w TMinw TMax w \text{TMax}_w TMaxw之间数字的映射,写作 B2T w :   { 0 , 1 } → ( TMin w , . . . , TMax w \text {B2T}_w: \space \{0,1\} \to ( \text{TMin}_w,...,\text{TMax}_w B2Tw: {01}(TMinw,...,TMaxw。同无符号表示一样,在可表示的取值范围内的每个数字都有一个唯一的 w w w 位的补码编码。

在这里插入图片描述从图中可知:
1.补码的范围是不对称的: ∣ TMin w ∣ = ∣ TMax w ∣ + 1 |\text{TMin}_w| = |\text{TMax}_w| +1 TMinw=TMaxw+1,也就是说,TMin 没有与之对应的正数。是因为一半的位模式(符号位设置为 1的数)表示负数,而另一半(符号位设置为0的数)表示非负数。因为 0 是非负数,也就意味着能表示的整数比负数少一个。
2.最大的无符号数值刚好比补码的最大值的两倍大一点: UMax w = 2 TMax w 十 1 \text{UMax}_w=2 \text{TMax}_w 十1 UMaxw=2TMaxw1。补码表示中所有表示负数的位模式在无符号表示中都变成了正数。注意-1和 UMax 有同样的位表示——一个全1的串。数值 0在两种表示方式中都是全 0 的串。

有符号数的其他表示方法

反码

除了最好有效位的权是 − ( w w − 1 − 1 ) -(w^{w-1}-1) (ww11) 而不是 − 2 w − 1 -2^{w-1} 2w1,它和补码是一样的:
B2O w ( x ⃗ ) = − x w − 1 ( 2 w − 1 − 1 ) + ∑ i = 0 w − 2 x i 2 i \text{B2O}_w(\vec x) = -x_{w-1}(2^{w-1} -1)+\sum_{i=0}^{w-2}x_i 2^i B2Ow(x )=xw1(2w11)+i=0w2xi2i

原码

最高有效位是符号位,用来确定剩下的位应该取负权还是正权:
B2S w ( x ⃗ ) = ( − 1 ) x w − 1 ⋅ ( ∑ i = 0 w − 2 x i 2 i ) \text{B2S}_w(\vec x) = (-1)^{x_{w-1}} {\cdot (\sum_{i=0}^{w-2}x_i 2^i)} B2Sw(x )=(1)xw1(i=0w2xi2i

有符号数与无符号数之间的转换

C 语言允许在各种不同的数字数据类型之间做强制类型转换。例如,假设变量 x 声明为int,u声明为 unsigned。表达式(unsigned)x 会将x的值转换成一个无符号数值,而(int)u将 u 的值转换成一个有符号整数。

考虑无符号与补码表示之间互相转换的结果。
对于在范围 0 < x < T M a x w 0<x<TMax_w 0<x<TMaxw之内的值而言,得到 T 2 U w ( x ) = x T2U_w(x)=x T2Uw(x)=x U 2 T w ( x ) = x U2T_w(x)=x U2Tw(x)=x。也就是说,在这个范围内的数字有相同的无符号和补码表示。
对于这个范围以外的数值,转换需要加上或者减去 2 w 2^w 2w

扩展一个数字的位表示

一个常见的运算是在不同字长的整数之间转换,同时又保持数值不变。当然,当目标数据类型太小以至于不能表示想要的值时,这根本就是不可能的。然而,从一个较小的数据类型转换到一个较大的类型,总是可能的。

要将一个无符号数转换为一个更大的数据类型,只要简单地在表示的开头添加0这种运算被称为零扩展(zero extension)。
要将一个补码数字转换为一个更大的数据类型,可以执行一个 符号扩展(sign extension) ,在表示中添加最高有效位的值。

截断数字

假设不用额外的位来扩展一个数值,而是减少表示一个数字的位数。
当将一个 w w w 位的数 x ⃗ = [ x w − 1 , x w − 2 , ⋅ ⋅ ⋅ , x 0 ] \vec x=[x_{w-1},x_{w-2},···,x_0] x =[xw1,xw2,⋅⋅⋅,x0] 截断为一个 k k k 位数字时,会丢弃高 w − k w-k wk 位,得到一个位向量 x ⃗ = [ x k − 1 , x k − 2 , . . . , x 0 ] \vec x=[x_{k-1},x_{k-2},...,x_0] x =[xk1,xk2,...,x0]。截断一个数字可能会改变它的值——溢出的一种形式。对于一个无符号数,可以很容易得出其数值结果。

整数运算

无符号加法

说一个算术运算溢出,是指完整的整数结果不能放到数据类型的字长限制中去。
在这里插入图片描述
当两个运算数的和为 2 w 2^w 2w 或者更大时,就发生了溢出。上图展示了字长 w = 4 w=4 w=4 的无符号加法函数的坐标图。这个和是按模 2 4 = 16 2^4=16 24=16 计算的。当 x + y < 16 x+y<16 x+y<16 时,没有溢出,并且 x + u 4 y x+ _u^4y x+u4y 就是 x 十 y x十y xy。这对应于图中标记为“正常”的斜面。当 x 十 y > 16 x十y>16 xy>16 时,加法溢出,结果相当于从和中减去 16 16 16。这对应于图中标记为“溢出”的斜面。

当执行 C 程序时,不会将溢出作为错误而发信号。不过有的时候,我们可能希望判定是否发生了溢出。

补码加法

对于补码加法,必须确定当结果太大(为正)或者太小(为负)时,应该做些什么。
首先,将两个加数的补码表示对齐,将它们的最高位对齐。然后,从最低位开始,一位一位地相加。
如果相加的结果超过了该位的表示范围(即进位),则将进位部分加到下一位的运算中。
最后,得到的结果就是两个加数的补码表示的和。
在这里插入图片描述

无符号乘法

范围在 0 ≤ x 0≤x 0x y ≤ 2 w − 1 y≤2^w-1 y2w1 内的整数 x x x y y y 可以被表示为 w w w 位的无符号数,但是它们的乘积 x ⋅ y x· y xy 的取值范围为 0 0 0 ( 2 w − 1 ) 2 = 2 2 w − 2 w + 1 + 1 (2^w - 1)^2 =2^{2w}-2^{w+1}+1 (2w1)2=22w2w+11 之间。这可能需要 2 w 2w 2w 位来表示。
不过,C语言中的无符号乘法被定义为产生 w w w 位的值,就是 2 w 2w 2w 位的整数乘积的低 w w w 位表示的值。我们将这个值表示为 α ∗ w u y α * _w^uy αwuy

乘以常数

x x x 为位模式 [ x w − 1 , x w − 2 , … , x 0 ] [x_{w-1},x_{w-2},…,x_0] [xw1,xw2,,x0] 表示的无符号整数。那么,对于任何 k ≥ 0 k≥0 k0,都认为 [ x w − 1 , x w − 2 , … , x 0 , 0 , … , 0 ] [x_{w-1},x_{w-2},…,x_0,0,…,0] [xw1xw2,,x0,0,,0] 给出了 x 2 k x2^k x2k w + k w+k wk 位的无符号表示,这里右边增加了 k k k 个 0。

因此,比如,当 w = 4 w=4 w=4 时, 11 11 11可以被表示为 [ 1011 ] [1011] [1011] k = 2 k=2 k=2 时将其左移得到 6 6 6 位向量 [ 101100 ] [101100] [101100],即可编码为无符号数 11 ⋅ 4 = 44 11·4=44 114=44

可以看出左移一个数值等价于执行一个与 2 的幂相乘的无符号乘法。

除以 2 的幂

除以⒉的幂也可以用移位运算来实现,只不过我们用的是右移。
无符号和补码数分别使用逻辑移位和算术移位来达到目的。

x x x 为位模式 [ x w − 1 , x w − 2 , … , x 0 ] [x_{w-1},x_{w-2},…,x_0] [xw1,xw2,,x0] 表示的无符号整数,而 k k k 的取值范围为 0 ≤ k < w 0≤k<w 0k<w。设 x ′ x^{'} x w − k w-k wk 位位表示 [ x w − 1 , x w − 2 , … , x k ] [x_{w-1},x_{w-2},…,x_k] [xw1,xw2,,xk] 的无符号数,而 x " x^{"} x" k k k 位位表示 [ x k − 1 , … , x 0 ] [x_{k-1},…,x_0] [xk1,,x0] 的无符号数。由此,我们可以看到 x = 2 k x ′ 十 x " x=2^kx^{'}十x^{"} x=2kxx",而 0 ≤ x " < 2 k 0≤x^{"}<2^k 0x"<2k。因此,可得 x / 2 k x/2^k x/2k 向上取整等于 x ′ x^{'} x
对位向量 [ x w − 1 , x w − 2 , … , x 0 ] [x_{w-1},x_{w-2},…,x_0] [xw1,xw2,,x0] 逻辑右移 k k k 位会得到位向量 [ 0 , … , 0 , x w − 1 , x w − 2 , … , x k ] [0,…,0,x_{w-1},x_{w-2},…,x_k] [0,,0,xw1,xw2,,xk],这个位向量有数值 x ′ x^{'} x,可以看到,该数值可通过计算 x>>k 得到。

浮点数

二进制小数

十进制表示法使用如下形式的表示:
d m d m − 1 . . . d 1 d 0 d − 1 d − 2 . . . d − n d_{m}d_{m-1}...d_{1}d_{0}d_{-1}d_{-2}...d_{-n} dmdm1...d1d0d1d2...dn

其中每个十进制数 d i d_i di 的取值范围是 0   9 0~9 0 9。这个表达描述的数值 d d d 定义为:
d = ∑ i = − n n 1 0 i × d i d=\sum_{i=-n}^{n}10^{i} \times d_i d=i=nn10i×di

数字权的定义与十进制小数点符号(“ . . .’)相关,这意味着小数点左边的数字的权是 10 的正幂,得到整数值,而小数点右边的数字的权是 10 的负幂,得到小数值。

二进制数字表述为:
b = ∑ i = − n m 2 i × b i b=\sum_{i=-n}^{m}2^{i}\times b_{i} b=i=nm2i×bi

符号.现在变为了二进制的点,点左边的位的权是 2 的正幂,点右边的位的权是 2 的负幂。
在这里插入图片描述

IEEE 浮点表示

IEEE 浮点标准用 V = ( − 1 ) s × M × 2 E V=(-1)^{s}\times M \times 2^{E} V=(1)s×M×2E 的形式来表示一个数:
符号(sign) s 决定这数是负数(s=1)还是正数(s=0),而对于数值 0 的符号位解释作为特殊情况处理。
尾数(significand) M 是一个二进制小数,它的范围是 1~2,或者是 0~1。
阶码(exponent) E 的作用是对浮点数加权,这个权重是 2的 E次幂(可能是负数)。将浮点数的位表示划分为三个字段,分别对这些值进行编码:
一个单独的符号位 s 直接编码符号 s;
k 位的阶码字段 e x p = e k − 1 ⋅ ⋅ ⋅ e 1 e 0 exp=e_{k-1}···e_1e_0 exp=ek1⋅⋅⋅e1e0 编码阶码 E;
n 位小数字段 f r a c = f 1 f 0 frac=f_1f_0 frac=f1f0 编码尾数 M,但是编码出来的值也依赖于阶码字段的值是否等于 0。

浮点运算

IEEE 标准指定了一个简单的规则,来确定诸如加法和乘法这样的算术运算的结果把浮点值z 和y 看成实数,而某个运算 ⊙ \odot 定义在实数上,计算将产生 R o u n d ( x ⊙ y ) Round(x\odot y) Round(xy) ,这是对实际运算的精确结果进行舍入后的结果。在实际中,浮点单元的设计者使用一些聪明的小技巧来避免执行这种精确的计算,因为计算只要精确到能够保证得到一个正确的舍人结果就可以了。当参数中有一个是特殊值(如-0、 − ∞ -\infty 或 NaN)时,IEEE 标准定义了一些使之更合理的规则。例如,定义 1/一0将产生 − ∞ -\infty ,而定义 1 / + 0 1/+0 1/+0 会产生 + ∞ +\infty +

IEEE 标准中指定浮点运算行为方法的一个优势在于,它可以独立于任何具体的硬件或者软件实现。因此,我们可以检查它的抽象数学属性,而不必考虑它实际上是如何实现的。

深入理解计算机系统(第三版)学习笔记

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/314729.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

地表最强,接口调试神器Postman ,写得太好了!

postman是一款支持http协议的接口调试与测试工具&#xff0c;其主要特点就是功能强大&#xff0c;使用简单且易用性好 。 无论是开发人员进行接口调试&#xff0c;还是测试人员做接口测试&#xff0c;postman都是我们的首选工具之一 。 那么接下来就介绍下postman到底有哪些功…

连续多级主管

背景 组织中一般会有个直接主管&#xff0c;或者汇报主管&#xff0c;有的组织可能有多个主管&#xff0c;更有甚者一个人能可能在不同的业务项目中&#xff0c;这样这个人可能存在n个主管&#xff0c;这样在设计流程中就会衍生出很多问题来。一起看一款审批软件的设置&#x…

加入 The Sandbox,在「小王子:友谊与慈善的冒险」中踏上奇幻旅途

这次体验不仅是一次冒险&#xff0c;更是一次充满爱心的愉悦探索。此外&#xff0c;您购买的 NFT 还将用于慈善教育项目&#xff1a;它由安托万德圣埃克苏佩里青少年基金会资助&#xff0c;其中一部分销售收入将用于支持这个慈善机构。这次寓教于乐的旅程交织着对爱、友谊的思考…

MySQL比较运算符详解

MySQL比较运算符详解 一、常用的比较运算符二、比较运算符的使用方法2.1 等于运算符&#xff08;&#xff09;2.2 不等于运算符&#xff08;<>或!&#xff09;2.3 大于运算符&#xff08;>&#xff09;2.4 小于运算符&#xff08;<&#xff09;2.5 大于等于运算符&…

开源云真机平台-Sonic实际使用过程踩坑及解决方法(持续更新)

开源云真机平台-Sonic实际使用过程踩坑及解决方法(持续更新) 1、执行Python 自定义脚本时requests文件报错 Script stderrTraceback (most recent call last): File "D:TestToolssonic-agent-2.6 2-windows x86 64 onic-ent-v2.6.2-windows X86 64tes-utDut2b713b90-493-…

【MFC实践】基于MFC向导C++制作计算器(附文件)

一、写在前面1.1 什么是MFC向导&#xff1f;1.2 使用MFC向导制作计算器1.3安装visual studio 2022和MFC插件 二、设计计算器界面1.1 新创建MFC项目1.2 设计计算器界面1.3 添加相关变量1.4 算法的一些问题及解决方式1.5 计算功能的实现1.6 其它功能的实现1.6.1 DEL功能1.6.2 C置…

Linux——firewalld防火墙(二)

一、firewalld高级配置 1、IP地址伪装 地址伪装&#xff08;masquerade):通过地址伪装&#xff0c;NAT设备将经过设备的包转发到指定接收方&#xff0c;同时将通过的数据包的源地址更改为其自己的接口地址。当返回的数据包到达时&#xff0c;会将目的地址修改为原始主机的地址…

(26)Linux 进程通信之共享内存(共享储存空间)

共享内存是System V版本的最后一个进程间通信方式。共享内存&#xff0c;顾名思义就是允许两个不相关的进程访问同一个逻辑内存&#xff0c;共享内存是两个正在运行的进程之间共享和传递数据的一种非常有效的方式。不同进程之间共享的内存通常为同一段物理内存。进程可以将同一…

6.4、SDN在云数据中心的应用案例分析

云数据中心中的虚拟子网包含网关和IP网段,IP分配给各个服务器,服务器间能够互相通信或通过网关访问外部网络。 在SDN云数据中心内,用户可以随时订购任意网段的虚拟子网,而且这些子网是可以在不同用户之间复用的,也就是说,不同用户可以使用相同的私有网段。 SDN云数据中心…

Matlab 字符识别OCR实验

Matlab 字符识别实验 图像来源于屏幕截图&#xff0c;要求黑底白字。数据来源是任意二进制文件&#xff0c;内容以16进制打印输出&#xff0c;0-9a-f’字符被16个可打印字符替代&#xff0c;这些替代字符经过挑选&#xff0c;使其相对容易被识别。 第一步进行线分割和字符分割…

从“唯分论”到“过程评价” 助力教育高质量发展

近日,为推动教育评价改革工作高质量发展,山东省委办公厅、省政府办公厅印发《关于进一步推进教育评价改革工作的若干措施》,从学校评价改革、学生评价改革等6方面共提出25条举措,对教育评价改革进行了全面部署。 教育评价改革是教育改革的“牛鼻子”,为教育发展提供了明确的方…

CSS 中的伪装大师:伪类和伪元素的奇妙世界

&#x1f90d; 前端开发工程师&#xff08;主业&#xff09;、技术博主&#xff08;副业&#xff09;、已过CET6 &#x1f368; 阿珊和她的猫_CSDN个人主页 &#x1f560; 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 &#x1f35a; 蓝桥云课签约作者、已在蓝桥云…

开源大数据集群部署(四)Freeipa部署(kerberos+ldap)

作者&#xff1a;櫰木 1、 FreeIPA介绍 Kerberos协议只是一种协议标准的框架&#xff0c;而MIT Kerberos则是实现了该协议的认证服务&#xff0c;是Kerberos的物理载体。将它与Hadoop服务进行集成便能够很好地解决安全性不足的问题。 除了需要安装MIT Kerberos之外&#xff0…

调查问卷设计指南:提升数据收集与分析效果的实用技巧

想要做好一份调查问卷要明确哪几点&#xff1f; 一、问卷三要素 1、问卷主题 我们使用调查问卷法进行调查的时候&#xff0c;首先要明确主题是什么&#xff0c;是关于人员满意度调查、人员喜好类型调查还是其他主题。明确主题后我们才可以进行接下来的动作。 2、调查人群 明确问…

互联网 HR 眼中的好简历是什么样子的?

HR浏览一份简历也就25秒左右&#xff0c;如果你连「好简历」都没有&#xff0c;怎么能找到好工作呢&#xff1f; 如果你不懂得如何在简历上展示自己&#xff0c;或者觉得怎么改简历都不出彩&#xff0c;那请你一定仔细读完。 互联网运营个人简历范文> 男 22 本科 AI简历…

数据类型、数据类型转换(Java)

一、数据类型的分类 1. byte&#xff1a;1字节&#xff0c;-128~127 2. short&#xff1a;2字节&#xff0c;-32768~32767 3. int&#xff1a;4字节 默认整型 4. long&#xff1a;8字节 注意&#xff1a;随便写一个整型字面量会默认是整型的&#xff0c;所以我们在写一个…

Docker 安装部署

1、Docker 安装 ① 卸载docker&#xff0c;清空之前的docker文件 yum remove docker \docker-client \docker-client-latest \docker-common \docker-latest \docker-latest-logrotate \docker-logrotate \docker-selinux \docker-engine-selinux \docker-engine \docker-ce…

挑选富集分析结果 enrichments

#2.2挑选term---selected_clusterenrichenrichmets[grepl(pattern "cilium|matrix|excular|BMP|inflamm|development|muscle|vaso|pulmonary|alveoli",x enrichmets$Description),]head(selected_clusterenrich) distinct(selected_clusterenrich)# remove duplica…

2. Presto应用

该笔记来源于网络&#xff0c;仅用于搜索学习&#xff0c;不保证所有内容正确。文章目录 1、Presto安装使用2、事件分析3、漏斗分析4、漏斗分析UDAF开发开发UDF插件开发UDAF插件 5、漏斗测试 1、Presto安装使用 参考官方文档&#xff1a;https://prestodb.io/docs/current/ P…

如何有效提高矢量网络分析仪的动态范围

动态范围是网络分析仪&#xff08;VNA&#xff09;接收机的最大输入功率与最小可测量功率&#xff08;本底噪声&#xff09;之间的差值&#xff0c;如图所示&#xff0c;要使测量有效&#xff0c;输入信号必须在这些边界内。 如果需要测量信号幅度非常大的变化&#xff0c;例如…