信息的表示和处理 及 CS:APP 15213 datalab
2019-06-04 19:48
1686 查看
信息的表示和处理
在通用计算机中中,
字节作为最为最小 的可寻址的内存单元,而不是访问内存中单独的位。
寻址和字节顺序
big endian
(大端法),数据最高字节部分地址在地址处,和人的感觉逻辑相似little endian
(小端法),低字节部分在低地址处
布尔代数
1
TRUE2
FALSE~
NOT&
AND|
OR^
EXCLUSIVE-OR(异或) 1 ^ 0 = 1- 1 ^ 1 = 0
- 0 ^ 0 = 0
- 0 ^ 1 = 1
IEEE 754 浮点数
$ V = (-1)^s \times M \times 2^E$
- 符号(sign) s(1)为负数, s(0)为非负数
- 尾数(significand) M 是一个二进制小数, 范围为 $1 \sim 2 - \varepsilon $ 或者 \(0 \sim 1 - \varepsilon\)
- 阶码(exponent) E的作用是对浮点数加权, 权重的范围为2的 E 次方幂
将浮点数的位划分位三个字段,分别对这些值赋值:
- 一个单独的符号位 s 直接编码符号位 s, 1-bit
- k 位的阶码字段 \(exp = e_{k-1} \cdots e_1 e_0\) 编码阶码 E,
k=7
(单精度),k=11
(双精度) - n 位小数字段 \(frac = f_{n-1} \cdots f_1 f_0\) 编码尾数 M, 且编码的值依赖阶码字段的值是否等于 0,
n=23
(单精度),n=52
(双精度)
浮点数的值:
- e 为无符号整数,其位表示 \(e_{k-1} \cdots e_1 e_0\)
- 小数字段 frac 被解释为描述小数值 \(f\), 其中 \(0 \le f \le 1\), 其二进制表示\(0.f_{n-1} \cdots f_1 f_0\)
- Bias 是一个等于 $2^{k-1} -1 $ 的偏置值
- 规格化\((exp !=0, exp != 2^{k}-1)\), 最常遇到的值 阶码的值 \(E = exp - Bias\)
- 尾数定义 \(M = 1 + f\)
-
阶码的值 $E = 1 - Bias $
NaN
舍入
表示方法限制了浮点数的范围和精度
偶数舍入(round-to-even)为默认的舍入方式, 其将数字向上或向下舍入,使得结果的
最低有效数字(保留位)是偶数(0)
只有是在两个可能的结果的中间值才考虑向偶数舍入, 大于 0.5 是直接进位的
向上舍入的情况,向下舍入可以不管(反正要丢弃了,不影响结果)
尾数 \(1.BBGRXXX\), 保留位(Guard bit)、近似位(Round bit) 和 粘滞位(Sticky bit)
- Round = 1, Sticky = 1 > 0.5 进位
- Guard = 1, Round = 1, Sticky = 0 -> 偶数向上舍入
实验部分
1. 只用
~和
&操作符求两个数的或
摩根定律: $ \neg(p \lor q) = \neg p \land \neg q $
异或:$ p \oplus q = (\neg p \land q) \lor (p \land \neg q)$
所以展开即可
/* * bitXor - x^y using only ~ and & * Example: bitXor(4, 5) = 1 * Legal ops: ~ & * Max ops: 14 * Rating: 1 */ int bitXor(int x, int y) { return ~(~(~x & y) & ~(x & ~y)); }
2. 最小的整形补码, 可用符号
! ~ & ^ | + << >>
$ -2^{31} $ (0xF0000000)
/* * tmin - return minimum two's complement integer * Legal ops: ! ~ & ^ | + << >> * Max ops: 4 * Rating: 1 */ int tmin(void) { return 1 << 31; }
3. 判断是否是最大的整形数,可用符号
! ~ & ^ | +*
直接利用 INT_MAX + INT_MAX + 2 = 0 的结果并且排除0xFFFFFFFF,还要注意一个不能直接相加,只能 x+1+x+1
/* * isTmax - returns 1 if x is the maximum, two's complement number, * and 0 otherwise * Legal ops: ! ~ & ^ | + * Max ops: 10 * Rating: 2 */ int isTmax(int x) { return !(x + 1 + x + 1) & !!(x + 1); }
4. 判断所有的奇数位为1,可用符号
! ~ & ^ | + << >>
排除偶数位的干扰得到奇数位的值,再与奇数位的 0xaaaaaaaa 做亦或运算,如果正确结果必为 0,这时做 非运算 就可以了
所有先得到 0xaaaaaaa
/* * allOddBits - return 1 if all odd-numbered bits in word set to 1 * Examples allOddBits(0xFFFFFFFD) = 0, allOddBits(0xAAAAAAAA) = 1 * Legal ops: ! ~ & ^ | + << >> * Max ops: 12 * Rating: 2 */ int allOddBits(int x) { int bits0_15 = (0xAA << 8) + 0xAA; int bits0_23 = (bits0_15 << 8) + 0xAA; int bits0_31 = (bits0_23 << 8) + 0xAA; return !((bits0_31 & x) ^ bits0_31); }
5.取负,可用符号
! ~ & ^ | + << >>
/* * negate - return -x * Example: negate(1) = -1. * Legal ops: ! ~ & ^ | + << >> * Max ops: 5 * Rating: 2 */ int negate(int x) { return ~x + 1; }
6. 判断是否是 ASCII 数字,可用符号
! ~ & ^ | + << >>
- 判断高 6_31 位,必须是 0
- 判断 4 5 位,必须为 1
- 判断第四位,通过相加6判断是否有进位
/* * isAsciiDigit - return 1 if 0x30 <= x <= 0x39 (ASCII codes for characters '0' * to '9') Example: isAsciiDigit(0x35) = 1. isAsciiDigit(0x3a) = 0. * isAsciiDigit(0x05) = 0. * Legal ops: ! ~ & ^ | + << >> * Max ops: 15 * Rating: 3 */ int isAsciiDigit(int x) { int bit6_31 = !((x >> 6) & (~0)); int bit_5 = (x & 0x20) >> 5; int bit_4 = (x & 0x10) >> 4; int bits0_3 = !(((x & 0xF) + 6) & 0x10); return bits0_3 & bit_4 & bit_5 & bit6_31; }
7. 条件判断,三目运算符, 可用字符
! ~ & ^ | + << >>
思路:由于
X & 0xFFFFFFFF = X, X & 0x0 = 0, 将两个数和 0xFFFFFFFF, 0x0 做与操作,再相加
- 只需要找到什么时候为 0xFFFFFFFF 和 0x0, 注意这两者可通过
~
得到
/* * conditional - same as x ? y : z * Example: conditional(2,4,5) = 4 * Legal ops: ! ~ & ^ | + << >> * Max ops: 16 * Rating: 3 */ int conditional(int x, int y, int z) { int flag = (!!x + ~0); return (z & flag) + (y & ~flag); }
8. 小于等于 可用字符
! ~ & ^ | + << >>
思路:判断相等,同符号相减判断是否有进位,不同符号直接判断第一个数的符号是否为 正
/* * isLessOrEqual - if x <= y then return 1, else return 0 * Example: isLessOrEqual(4,5) = 1. * Legal ops: ! ~ & ^ | + << >> * Max ops: 24 * Rating: 3 */ int isLessOrEqual(int x, int y) { int equal = !(x ^ y); // x == y int same_sign = !((x ^ y) >> 31); // sign int x_reduce_y = ~y + 1 + x; return equal | (same_sign & (x_reduce_y >> 31)) | ((!same_sign) & (x >> 31) & 1); }
9. 非运算符 可用字符
! ~ & ^ | + << >>
思路:核心就是抓住 符号位判断
- 考虑取反还是取负,取反所有数字的符号位都改变,取负只有 0 和 0x80000000 符号位不变,且这两个符号位相反,所以用取负的方式
- 将数与其负数
直接
做与操作,只有 0x80000000,符号为 1 不变,不能筛选出 0 的情况 - 考虑别的情况,将数
取反
做与操作,符号相反的数与操作后仍然为 0, 0x800000000 取反(符号为0)与其负数(符号为0)相与也还为 0,只有0取反后符号为1,与操作后仍为1
/* * logicalNeg - implement the ! operator, using all of * the legal operators except ! * Examples: logicalNeg(3) = 0, logicalNeg(0) = 1 * Legal ops: ~ & ^ | + << >> * Max ops: 12 * Rating: 4 */ int logicalNeg(int x) { return ((~x & ~(~x + 1)) >> 31) & 0x1; }
10. 计算一个最少的补码位可以表达的位数 可用字符
! ~ & ^ | + << >>
思路:将相邻位做亦或操作,找到最高的位为 1 所在的位
~(bits16 << 3) + 1) + (((bits16 ^ 1) & 0x1) << 3, bits* 为上一个移位的结果,利用这个结果判断是增加位移的大小
/* howManyBits - return the minimum number of bits required to represent x in * two's complement * Examples: howManyBits(12) = 5 * howManyBits(298) = 10 * howManyBits(-5) = 4 * howManyBits(0) = 1 * howManyBits(-1) = 1 * howManyBits(0x80000000) = 32 * Legal ops: ! ~ & ^ | + << >> * Max ops: 90 * Rating: 4 */ int howManyBits(int x) { // all assignment must be followed by a declaration. int bits16, bits8, bits4, bits2, bits1; int shift16, shift8, shift4, shift2, shift1; int shift_off = 16; // first shift offset x ^= x << 1; // find the highest 1-bit after XOR adjacent bits bits16 = !(x >> shift_off); shift16 = bits16 << 4; // binary search. // if result of prev offset != 0, shift_off should be increasing half prev // offset , else should be decreasing half. shift_off = shift_off + (~(bits16 << 3) + 1) + (((bits16 ^ 1) & 0x1) << 3); bits8 = (!(x >> shift_off)); shift8 = bits8 << 3; shift_off = shift_off + (~(bits8 << 2) + 1) + (((bits8 ^ 1) & 0x1) << 2); bits4 = (!(x >> shift_off)); shift4 = bits4 << 2; shift_off = shift_off + (~(bits4 << 1) + 1) + (((bits4 ^ 1) & 0x1) << 1); bits2 = (!(x >> shift_off)); shift2 = bits2 << 1; shift_off = shift_off + (~(bits2) + 1) + ((bits2 ^ 1) & 0x1); bits1 = (!(x >> shift_off)); shift1 = bits1; }
11. 计算浮点数 f 2, 返回浮点数的二进制位表示, 可用符号不受限制*
思路:由于尾数的值取决于 frac 和 exp,所以要对其分开处理
- 对于规格数,exp + 1, 但要考虑 +1 后不能为 255
- 对于非规格数 exp = 255, 直接返回参数
- exp = 0, frac = 0 返回 0, 因为这就是个 0
- exp = 0, frac != 0, frac 左移一位(尾数取值的问题),又要判断左移后是否溢出(0-22bit)
/* * float_twice - Return bit-level equivalent of expression 2*f for * floating point argument f. * Both the argument and result are passed as unsigned int's, but * they are to be interpreted as the bit-level representation of * single-precision floating point values. * When argument is NaN, return argument * Legal ops: Any integer/unsigned operations incl. ||, &&. also if, while * Max ops: 30 * Rating: 4 */ unsigned float_twice(unsigned uf) { int exp = 0x7f800000 & uf; int frac = 0x007FFFFF & uf; int sign = 0x80000000 & uf; int bias = (exp >> 23) - 127; if (uf == 0x0) return 0; if (bias == 128) // NaN return NaN, inf can't *2 return uf; // frac depends on exp, so exp could not add 1 alone. if (exp == 0) { // (exp + frac) << 1 frac = (frac << 1) & 0x007FFFFF; if (uf & 0x00400000) exp = 0x00800000; } else { exp = (exp + 0x00800000) & 0x7F800000; if (exp == 0x7F800000) frac = 0; } uf = sign | exp | frac; return sign | exp | frac; }
12. 整数转浮点数,返回浮点数的二进制位表示, 可用符号不受限制
思路:核心在于发现该数的绝对值的最高位 1 对应浮点数隐式精度的 1, 然后最高位1后的23位排列在 frac 位置
- 取数的绝对值,后面对非负数数进行操作
- 取最少可以表达整数(最高位 1)的 k 位 inum,
- 所在的位数 n 整数i转浮点数f 在位模式上为 将 k-1 .. k-2 .. 0 放置在浮点数的 frac 部分,非规格数有一个隐式 1, 代替数字有效最高位 1
- 由上精度有限制,有效位的前23位充当尾数部分,要对后9位进行判断是否需要舍入
- 将 exp = 127 + n
- 符号位不变
- 其他 0 等情况考虑
/* * float_i2f - Return bit-level equivalent of expression (float) x * Result is returned as unsigned int, but * it is to be interpreted as the bit-level representation of a * single-precision floating point values. * Legal ops: Any integer/unsigned operations incl. ||, &&. also if, while * Max ops: 30 * Rating: 4 */ unsigned float_i2f(int x) { unsigned abs_x = x; unsigned sign = x & 0x80000000; int flag = 0; int n = 30; if (x == 0) return x; else if (x == 0x80000000) return 0xcf000000; if (sign) abs_x = -x; while (!(abs_x & (1 << n))) n--; abs_x <<= 32 - n; if ((abs_x & 0x01ff) > 0x0100) flag = 1; else if ((abs_x & 0x03ff) == 0x0300) flag = 1; else flag = 0; return sign + ((n << 23) + 0x3F800000) + (abs_x >> 9) + flag; }
13. 浮点数转整数,返回整数的二进制位表示, 可用符号不受限制
思路:有上面的
float_i2f()做铺垫,
- 集中在对精度的处理, 对于 exp 大于 31,超过整形的表达范围
- 小于 23,值不发生改变,右移 23 - exp
- 大于 23 小于等于 31,值发生改变 左移 exp -23
/* * float_f2i - Return bit-level equivalent of expression (int) f * for floating point argument f. * Argument is passed as unsigned int, but * it is to be interpreted as the bit-level representation of a * single-precision floating point value. * Anything out of range (including NaN and infinity) should return * 0x80000000u. * Legal ops: Any integer/unsigned operations incl. ||, &&. also if, while * Max ops: 30 * Rating: 4 */ int float_f2i(unsigned uf) { unsigned sign = uf & 0x80000000; unsigned exp = uf & 0x7F800000; unsigned frac = uf & 0x007FFFFF; if (uf == 0x7F800000) return 0x80000000; else if (uf == 0) return 0; if (exp == 0) return 0; int m = 0x00800000 + frac; int e = (exp >> 23) - 127; if (e < 0) return 0; else if (e > 31) return 0x80000000; else if (e < 23) m >>= (23 - e); else m <<= (e - 23); if (sign) m = -m; return sign | m; }
相关文章推荐
- CS-APP CP2 信息的表示和处理
- Learning by doing 二 深入理解计算机系统(CS:APP)一信息表示
- 关于如何获取上线后的app异常信息(bug)处理
- CSAPP阅读笔记——第二章:信息的表示和处理
- 信息的表示和处理(1)
- 信息的表示和处理(4)
- [CSAPP]信息的表示和处理
- Fiddler的抓包处理,显示手机app页面信息
- CS:app 读书笔记----循环体的机器级表示及优化
- 第二章.《信息的表示和处理》
- 《深入理解计算机系统》笔记一:信息的表示与处理(3)——整数的转换、扩展、截断和运算
- 计算机中信息的表示与处理
- 深入理解计算机系统--信息表示和处理
- 深入理解计算机系统-第二章-信息的表示和处理-2.7
- 信息的表示和处理--信息存储
- 一种基于信息状态的 信息表示、存储和处理系统
- 深入理解计算机系统--信息的表示和处理
- 查看iOS已上架App的Crash信息定位、应对处理方式的实例
- 计算机中信息的表示与处理
- GIS+=地理信息+行业+大数据——基于云环境流处理平台下的实时交通创新型app