mobile wallpaper 1mobile wallpaper 2mobile wallpaper 3mobile wallpaper 4
1929 字
5 分钟
bits
2026-06-22
2026-05-25

信息的处理和表示#

数字的存储#

内存被划分为不同大小的字块,32位CPU->4字节,64位CPU->8字节 对字长ww的机器而言,虚拟地址范围为02w10~2^w-1,即有2w2^w个字节 64位架构地址空间限制为48位虚拟地址,约为256TB256TB(248Bytes2^{48}Bytes),但是仍然在64位逻辑上处理算术运算 编译器通过保持字节对齐,提高硬件效率 无论32位机器还是64位机器,int32_tint64_t都分别占4个和8个字节;intlong等C类型的大小取决于具体ABI。32位机器也可以支持64位整数运算,只是通常需要用多条32位指令协同完成 而浮点寄存器有自己的宽度标准,与通用寄存器宽度无关,如doubledouble始终占8个字节

小端法:最低有效位所在字节存储地址在最前面,类型转换灵活,符合数学思维 大端法:最高有效位所在字节存储地址在最前面,方便阅读识别,便于判断正负 大小端法通常由ISA/系统ABI共同约定,有些架构还支持在不同模式下选择字节序 x86/x86-64使用小端法 PowerPC,网络协议(TCP/IP)使用大端法 ARM, RISC-V, MIPS等同时支持两种字节序

二进制下的整数#

1. 补码#

对于 ww 位的无符号整数xxx=i=0w1ai×2ix = \sum\limits_{i=0}^{w-1}a_i \times2^i 对于ww位的有符号整数xx : x=2w1×aw1+i=0w2ai×2ix = -2^{w-1} \times a_{w - 1}+\sum\limits_{i=0}^{w-2}a_i \times2^i(补码表示) 在此种表示方式下,x-x的补码编码与无符号整数2wx2^w-x的编码相同 原理:在modmod 2w2^w 意义下 x-x2wx2^w - x等价,无符号运算在溢出的情况下仍满足加法与乘法结合律,交换律等定律 无符号整数与有符号整数的比较:有符号整数类型转换为无符号整数再进行比较 egeg: 1-1 >> 0U0U 有符号整数与无符号整数的转换: 若有符号数t<0t < 0,则其无符号解释为t+2wt + 2^w;若t0t \geq 0,则无符号解释仍为tt 若无符号数u>2w11u > 2^{w-1}-1,则其有符号解释为u2wu - 2^w;否则仍为uu

2.符号扩展与数字截断#

符号扩展:在不改变值的情况下提升一个ww位有符号整数的位数

case1<若符号位>aw1=0a_{w-1} = 0

直接将awa_w设为00,扩展到了w+1w+1

case2<若符号位>aw1=1a_{w-1}=1

将第awa_w设为11,第awa_waw1a_{w-1}的贡献从2w1-2^{w-1}2w+2w1-2^{w}+2^{w-1}不变,扩展到了w+1w+1位 即扩展到第w+1w+1位时有aw=aw1a_w=a_{w-1}

数字截断到kk位:保留最低kk位,舍弃第kk位及更高位 无符号数数字截断等价于对2k2^k取模

从较小整数类型转换到较大整数类型时,C会先进行整数提升:有符号源通常符号扩展,无符号源通常零扩展,然后再按目标类型解释位模式 eg. 对于short x; (unsigned)x等价于(unsigned)(int)x

3.运算#

对于两个ww位整数的运算,加法得到的结果最多为w+1w+1位,截断第w+1w+1位得到ww位整数,对无符号整数来说等价于对结果modmod 2w2^w 乘法得到的结果最多为2w2w位,保留低ww位并舍弃高位得到ww位整数 ww位整数与常数相乘的时候,编译器会根据上下文进行优化,优化方式取决于架构的指令集 eg. x*14=(x<<3)+(x<<2)+(x<<1)或((x<<3)-x)<<2(乘法分解为位移和加减法) 或imul eax, edi, 14(编译器认为imul更快,直接使用乘法指令)

逻辑右移:右移一位后在最高位补0 算术右移:右移一位后,若符号位原本为1,则在最高位补1,否则补0 除以2的幂时: 无符号数采用逻辑右移,等价于向下取整 有符号数需要特殊处理:编译器会生成先加偏置再算术右移的代码,以保证向零取整的结果与C语言标准一致

二进制下的浮点数#

1.浮点数的表示#

标准化之前#

对浮点数xx有:x=i=jkai×2ix=\sum \limits_{i=-j}^{k}a_i \times2^i 左移,右移在算术上仍然等价于×2\times2÷2\div 2,但是误差大,受位数有限制约 标准浮点数表示法:IEEE浮点数

IEEE浮点数#

符号位(s) + 阶码位(exp) + 尾数位(frac) 单精度32位 双精度64位 (和英特尔扩展精度80位) 32 = 1 + 8 + 23 64 = 1 + 11 + 52

IEEE浮点标准用V=(1)s×2EMV=(-1)^s \times 2^E * M表示浮点数

image

exp=i=0k12ieiexp=\sum\limits_{i=0}^{k-1}2^ie_i,bias=2k11bias=2^{k-1}-1(无符号整数) frac=i=0n1fi×2infrac = \sum\limits_{i=0}^{n-1}f_i\times2^{i-n}(分数)

1.规格化的情况(1exp2k21 \leq exp \leq 2^k-2) E=expbiasE=exp-biasM=1.0+fracM=1.0 + frac,那么有2k1+2E2k11-2^{k-1} + 2 \leq E \leq 2^{k-1} -1

2.非规格化的情况(exp=0exp = 0) E=1biasE=1-biasM=fracM=frac 用来表示00和极其接近00的值 注:+0.0+0.00.0-0.0有不同的位表示,但在普通数值比较中相等

3.特殊值(exp=2k1exp = 2^k-1) frac=0frac = 0:V=INFV=INF frac0frac \neq 0:V=NaNV=NaN

注: 1.引入biasbias的意义:阶码无需引入符号位;对同号规格化浮点数,阶码和尾数的位模式顺序更接近数值大小顺序 2.非规格化情况下EE1bias1-bias,使得非规格化最大值为222k1×(12n)2^{2-{2^{k-1}}} \times (1-{2^{-n}}),而规格化最小值为222k12^{2-{2^{k-1}}},二者十分接近

2.整数转浮点数#

以将(int)114转换为float为例

1.转为二进制下科学计数法 114=(1110010)2=(1.110010)2×26114 = (1110010)_2 = (1.110010)_2 \times 2 ^ 6 2.去掉小数点前的1并在末尾添加0直到nn(23)位,得到尾数部分 1.110010>110010000000000000000001.110010 -> 11001000000000000000000 3.将阶数加上偏移值2k112^{k-1}-1(127),转为二进制得到阶码部分 6+127=133(10000101)26 + 127 = 133 = (10000101)_2 4.加上符号位,将阶码尾数拼起来 (01000010111001000000000000000000)2(01000010111001000000000000000000)_2

由该过程可知,整数二进制编码与其浮点数表示的尾数部分除第一个1外重合

3.思考:n位位数不能精确表示的最小正整数#

假设阶码足够大,有nn位尾数的浮点数不能精确表示的最小正整数为2n+1+12^{n+1}+1

证明:nn位的fracfrac再加上尾数隐式的1.01.0一共n+1n+1位,乘2E2^E可以看做左移EE位,在阶码可以取到无穷大的情况下,可以取遍12n+111 ~ 2^{n+1}-1,同时在fracfrac全为00的情况下,左移n+1n+1位得到2n+12^{n+1},即12n+11~2^{n+1}都可以表出,而2n+1+12^{n+1}+1无法表出 推论:double能连续精确表示的最大正整数为253=90071992547409922^{53}=9007199254740992,因此253+12^{53}+1不能被精确表示;但更大的2的幂或足够大的偶数仍可能精确表示 补充:nn位尾数浮点数在xx处的误差(可表示数的最小间隔) ULP(x)=2log2xnULP(x)=2^{\lfloor \log_2 \lvert x \rvert \rfloor - n} 警钟撅烂:double r = 1e18+5; rr的值仍然为101810^{18}

4.浮点数的运算#

舍入:找到最接近的值xx,使其可以按期望的浮点形式表示出来 向零舍入,向上舍入,向下舍入 向偶数舍入:优先向满足条件的最接近的数舍入,若存在两个这样的数,则向最低有效位为偶数的那个数舍入(避免了统计误差) 浮点加法,乘法运算不满足结合律,浮点乘法在加法上不存在分配律 **eg.**对于floatfloat1.14+1e181e18=01.14+1e18-1e18=0(舍入导致1.14丢失),1.14+(1e181e18)=1.141.14+(1e18-1e18)=1.14 无穷运算规则:+∞ + (+∞) = +∞,+∞ + (-∞) = NaN,+∞ × 0 = NaN NaN的传播特性:任何包含NaN的运算结果都是NaN

5.C中浮点数与有符号数的转换#

intintfloatfloat可能被舍入 doubledoublefloatfloat可能会溢出或者被舍入 float,doublefloat,double转整数值会向零舍入;若超出目标整数类型范围,C标准认为行为未定义。在常见x86实现中,越界或NaN转换可能产生整数不确定值(100..00)2(100..00)_2,即2w1-2^{w-1}

分享

如果这篇文章对你有帮助,欢迎分享给更多人!

bits
https://katyusha-blog.com/posts/csapp/notes/bits/
作者
katyusha
发布于
2026-06-22
许可协议
CC BY-NC-SA 4.0

部分信息可能已经过时

目录