信息的表示和处理

在通用计算机中中,字节作为最为最小 的可寻址的内存单元,而不是访问内存中单独的位。

寻址和字节顺序

  • big endian (大端法),数据最高字节部分地址在地址处,和人的感觉逻辑相似
  • little endian (小端法),低字节部分在低地址处

布尔代数

  • 1 TRUE
  • 2 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\)
  • 非规格化\((exp == 0)\), 提供表示数值 0 及逐渐接近 0 的方法
    • 阶码的值 $E = 1 - Bias $
    • 尾数定义 \(M = f\)
  • 非规格化\((exp == 2^{k}-1)\), 特殊值 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)$

所以展开即可

  1. /*
  2. * bitXor - x^y using only ~ and &
  3. * Example: bitXor(4, 5) = 1
  4. * Legal ops: ~ &
  5. * Max ops: 14
  6. * Rating: 1
  7. */
  8. int bitXor(int x, int y) {
  9. return ~(~(~x & y) & ~(x & ~y));
  10. }

2. 最小的整形补码, 可用符号 ! ~ & ^ | + << >>

$ -2^{31} $ (0xF0000000)

  1. /*
  2. * tmin - return minimum two's complement integer
  3. * Legal ops: ! ~ & ^ | + << >>
  4. * Max ops: 4
  5. * Rating: 1
  6. */
  7. int tmin(void) {
  8. return 1 << 31;
  9. }

3. 判断是否是最大的整形数,可用符号 ! ~ & ^ | +*

直接利用 INT_MAX + INT_MAX + 2 = 0 的结果并且排除0xFFFFFFFF,还要注意一个不能直接相加,只能 x+1+x+1

  1. /*
  2. * isTmax - returns 1 if x is the maximum, two's complement number,
  3. * and 0 otherwise
  4. * Legal ops: ! ~ & ^ | +
  5. * Max ops: 10
  6. * Rating: 2
  7. */
  8. int isTmax(int x) {
  9. return !(x + 1 + x + 1) & !!(x + 1);
  10. }

4. 判断所有的奇数位为1,可用符号 ! ~ & ^ | + << >>

排除偶数位的干扰得到奇数位的值,再与奇数位的 0xaaaaaaaa 做亦或运算,如果正确结果必为 0,这时做 非运算 就可以了

所有先得到 0xaaaaaaa

  1. /*
  2. * allOddBits - return 1 if all odd-numbered bits in word set to 1
  3. * Examples allOddBits(0xFFFFFFFD) = 0, allOddBits(0xAAAAAAAA) = 1
  4. * Legal ops: ! ~ & ^ | + << >>
  5. * Max ops: 12
  6. * Rating: 2
  7. */
  8. int allOddBits(int x) {
  9. int bits0_15 = (0xAA << 8) + 0xAA;
  10. int bits0_23 = (bits0_15 << 8) + 0xAA;
  11. int bits0_31 = (bits0_23 << 8) + 0xAA;
  12. return !((bits0_31 & x) ^ bits0_31);
  13. }

5.取负,可用符号 ! ~ & ^ | + << >>

  1. /*
  2. * negate - return -x
  3. * Example: negate(1) = -1.
  4. * Legal ops: ! ~ & ^ | + << >>
  5. * Max ops: 5
  6. * Rating: 2
  7. */
  8. int negate(int x) { return ~x + 1; }

6. 判断是否是 ASCII 数字,可用符号 ! ~ & ^ | + << >>

  1. 判断高 6_31 位,必须是 0
  2. 判断 4 5 位,必须为 1
  3. 判断第四位,通过相加6判断是否有进位
  1. /*
  2. * isAsciiDigit - return 1 if 0x30 <= x <= 0x39 (ASCII codes for characters '0'
  3. * to '9') Example: isAsciiDigit(0x35) = 1. isAsciiDigit(0x3a) = 0.
  4. * isAsciiDigit(0x05) = 0.
  5. * Legal ops: ! ~ & ^ | + << >>
  6. * Max ops: 15
  7. * Rating: 3
  8. */
  9. int isAsciiDigit(int x) {
  10. int bit6_31 = !((x >> 6) & (~0));
  11. int bit_5 = (x & 0x20) >> 5;
  12. int bit_4 = (x & 0x10) >> 4;
  13. int bits0_3 = !(((x & 0xF) + 6) & 0x10);
  14. return bits0_3 & bit_4 & bit_5 & bit6_31;
  15. }

7. 条件判断,三目运算符, 可用字符 ! ~ & ^ | + << >>

思路:由于 X & 0xFFFFFFFF = X, X & 0x0 = 0, 将两个数和 0xFFFFFFFF, 0x0 做与操作,再相加

  1. 只需要找到什么时候为 0xFFFFFFFF 和 0x0, 注意这两者可通过 ~ 得到
  1. /*
  2. * conditional - same as x ? y : z
  3. * Example: conditional(2,4,5) = 4
  4. * Legal ops: ! ~ & ^ | + << >>
  5. * Max ops: 16
  6. * Rating: 3
  7. */
  8. int conditional(int x, int y, int z) {
  9. int flag = (!!x + ~0);
  10. return (z & flag) + (y & ~flag);
  11. }

8. 小于等于 可用字符 ! ~ & ^ | + << >>

思路:判断相等,同符号相减判断是否有进位,不同符号直接判断第一个数的符号是否为 正

  1. /*
  2. * isLessOrEqual - if x <= y then return 1, else return 0
  3. * Example: isLessOrEqual(4,5) = 1.
  4. * Legal ops: ! ~ & ^ | + << >>
  5. * Max ops: 24
  6. * Rating: 3
  7. */
  8. int isLessOrEqual(int x, int y) {
  9. int equal = !(x ^ y); // x == y
  10. int same_sign = !((x ^ y) >> 31); // sign
  11. int x_reduce_y = ~y + 1 + x;
  12. return equal | (same_sign & (x_reduce_y >> 31)) | ((!same_sign) & (x >> 31) & 1);
  13. }

9. 非运算符 可用字符 ! ~ & ^ | + << >>

思路:核心就是抓住 符号位判断

  1. 考虑取反还是取负,取反所有数字的符号位都改变,取负只有 0 和 0x80000000 符号位不变,且这两个符号位相反,所以用取负的方式
  2. 将数与其负数直接做与操作,只有 0x80000000,符号为 1 不变,不能筛选出 0 的情况
  3. 考虑别的情况,将数取反做与操作,符号相反的数与操作后仍然为 0, 0x800000000 取反(符号为0)与其负数(符号为0)相与也还为 0,只有0取反后符号为1,与操作后仍为1
  1. /*
  2. * logicalNeg - implement the ! operator, using all of
  3. * the legal operators except !
  4. * Examples: logicalNeg(3) = 0, logicalNeg(0) = 1
  5. * Legal ops: ~ & ^ | + << >>
  6. * Max ops: 12
  7. * Rating: 4
  8. */
  9. int logicalNeg(int x) {
  10. return ((~x & ~(~x + 1)) >> 31) & 0x1;
  11. }

10. 计算一个最少的补码位可以表达的位数 可用字符 ! ~ & ^ | + << >>

思路:将相邻位做亦或操作,找到最高的位为 1 所在的位

~(bits16 << 3) + 1) + (((bits16 ^ 1) & 0x1) << 3, bits* 为上一个移位的结果,利用这个结果判断是增加位移的大小

  1. /* howManyBits - return the minimum number of bits required to represent x in
  2. * two's complement
  3. * Examples: howManyBits(12) = 5
  4. * howManyBits(298) = 10
  5. * howManyBits(-5) = 4
  6. * howManyBits(0) = 1
  7. * howManyBits(-1) = 1
  8. * howManyBits(0x80000000) = 32
  9. * Legal ops: ! ~ & ^ | + << >>
  10. * Max ops: 90
  11. * Rating: 4
  12. */
  13. int howManyBits(int x) {
  14. // all assignment must be followed by a declaration.
  15. int bits16, bits8, bits4, bits2, bits1;
  16. int shift16, shift8, shift4, shift2, shift1;
  17. int shift_off = 16; // first shift offset
  18. x ^= x << 1; // find the highest 1-bit after XOR adjacent bits
  19. bits16 = !(x >> shift_off);
  20. shift16 = bits16 << 4;
  21. // binary search.
  22. // if result of prev offset != 0, shift_off should be increasing half prev
  23. // offset , else should be decreasing half.
  24. shift_off = shift_off + (~(bits16 << 3) + 1) + (((bits16 ^ 1) & 0x1) << 3);
  25. bits8 = (!(x >> shift_off));
  26. shift8 = bits8 << 3;
  27. shift_off = shift_off + (~(bits8 << 2) + 1) + (((bits8 ^ 1) & 0x1) << 2);
  28. bits4 = (!(x >> shift_off));
  29. shift4 = bits4 << 2;
  30. shift_off = shift_off + (~(bits4 << 1) + 1) + (((bits4 ^ 1) & 0x1) << 1);
  31. bits2 = (!(x >> shift_off));
  32. shift2 = bits2 << 1;
  33. shift_off = shift_off + (~(bits2) + 1) + ((bits2 ^ 1) & 0x1);
  34. bits1 = (!(x >> shift_off));
  35. shift1 = bits1;
  36. return 32 + (~(shift1 + shift2 + shift4 + shift8 + shift16) + 1);
  37. }

11. 计算浮点数 f * 2, 返回浮点数的二进制位表示, 可用符号不受限制

思路:由于尾数的值取决于 frac 和 exp,所以要对其分开处理

  • 对于规格数,exp + 1, 但要考虑 +1 后不能为 255
  • 对于非规格数
    • exp = 255, 直接返回参数
    • exp = 0, frac = 0 返回 0, 因为这就是个 0
    • exp = 0, frac != 0, frac 左移一位(尾数取值的问题),又要判断左移后是否溢出(0-22bit)
  1. /*
  2. * float_twice - Return bit-level equivalent of expression 2*f for
  3. * floating point argument f.
  4. * Both the argument and result are passed as unsigned int's, but
  5. * they are to be interpreted as the bit-level representation of
  6. * single-precision floating point values.
  7. * When argument is NaN, return argument
  8. * Legal ops: Any integer/unsigned operations incl. ||, &&. also if, while
  9. * Max ops: 30
  10. * Rating: 4
  11. */
  12. unsigned float_twice(unsigned uf) {
  13. int exp = 0x7f800000 & uf;
  14. int frac = 0x007FFFFF & uf;
  15. int sign = 0x80000000 & uf;
  16. int bias = (exp >> 23) - 127;
  17. if (uf == 0x0)
  18. return 0;
  19. if (bias == 128) // NaN return NaN, inf can't *2
  20. return uf;
  21. // frac depends on exp, so exp could not add 1 alone.
  22. if (exp == 0) { // (exp + frac) << 1
  23. frac = (frac << 1) & 0x007FFFFF;
  24. if (uf & 0x00400000)
  25. exp = 0x00800000;
  26. } else {
  27. exp = (exp + 0x00800000) & 0x7F800000;
  28. if (exp == 0x7F800000)
  29. frac = 0;
  30. }
  31. uf = sign | exp | frac;
  32. return sign | exp | frac;
  33. }

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 等情况考虑
  1. /*
  2. * float_i2f - Return bit-level equivalent of expression (float) x
  3. * Result is returned as unsigned int, but
  4. * it is to be interpreted as the bit-level representation of a
  5. * single-precision floating point values.
  6. * Legal ops: Any integer/unsigned operations incl. ||, &&. also if, while
  7. * Max ops: 30
  8. * Rating: 4
  9. */
  10. unsigned float_i2f(int x) {
  11. unsigned abs_x = x;
  12. unsigned sign = x & 0x80000000;
  13. int flag = 0;
  14. int n = 30;
  15. if (x == 0)
  16. return x;
  17. else if (x == 0x80000000)
  18. return 0xcf000000;
  19. if (sign)
  20. abs_x = -x;
  21. while (!(abs_x & (1 << n)))
  22. n--;
  23. abs_x <<= 32 - n;
  24. if ((abs_x & 0x01ff) > 0x0100)
  25. flag = 1;
  26. else if ((abs_x & 0x03ff) == 0x0300)
  27. flag = 1;
  28. else
  29. flag = 0;
  30. return sign + ((n << 23) + 0x3F800000) + (abs_x >> 9) + flag;
  31. }

13. 浮点数转整数,返回整数的二进制位表示, 可用符号不受限制

思路:有上面的 float_i2f() 做铺垫,

  • 集中在对精度的处理, 对于 exp

    • 大于 31,超过整形的表达范围
    • 小于 23,值不发生改变,右移 23 - exp
    • 大于 23 小于等于 31,值发生改变 左移 exp -23
  • 由于浮点数的正负只由符号位影响,所以可以最后做取负操作。
  1. /*
  2. * float_f2i - Return bit-level equivalent of expression (int) f
  3. * for floating point argument f.
  4. * Argument is passed as unsigned int, but
  5. * it is to be interpreted as the bit-level representation of a
  6. * single-precision floating point value.
  7. * Anything out of range (including NaN and infinity) should return
  8. * 0x80000000u.
  9. * Legal ops: Any integer/unsigned operations incl. ||, &&. also if, while
  10. * Max ops: 30
  11. * Rating: 4
  12. */
  13. int float_f2i(unsigned uf) {
  14. unsigned sign = uf & 0x80000000;
  15. unsigned exp = uf & 0x7F800000;
  16. unsigned frac = uf & 0x007FFFFF;
  17. if (uf == 0x7F800000)
  18. return 0x80000000;
  19. else if (uf == 0)
  20. return 0;
  21. if (exp == 0)
  22. return 0;
  23. int m = 0x00800000 + frac;
  24. int e = (exp >> 23) - 127;
  25. if (e < 0)
  26. return 0;
  27. else if (e > 31)
  28. return 0x80000000;
  29. else if (e < 23)
  30. m >>= (23 - e);
  31. else
  32. m <<= (e - 23);
  33. if (sign)
  34. m = -m;
  35. return sign | m;
  36. }

信息的表示和处理 及 CS:APP 15213 datalab的更多相关文章

  1. 深入理解计算机系统 (CS:APP) Lab2 - Bomb Lab 解析

    原文地址:https://billc.io/2019/04/csapp-bomblab/ 写在前面 CS:APP是这学期的一门硬核课程,应该是目前接触到最底层的课程了.学校的教学也是尝试着尽量和CMU ...

  2. CS:APP配套实验 Data Lab

    刚刚完成注册博客,想写一篇随笔,方便以后自己回顾.如果恰好也能帮助到你,是我的荣幸. 这次随笔是记载我的计算机系统(CS:APP,Computer Systems:A Programer's Pers ...

  3. 图文并茂-超详解 CS:APP: Lab3-Attack(附带栈帧分析)

    CS:APP:Lab3-ATTACK 0. 环境要求 关于环境已经在lab1里配置过了.lab1的连接如下 实验的下载地址如下 说明文档如下 http://csapp.cs.cmu.edu/3e/at ...

  4. 深入理解计算机系统 (CS:APP) 缓冲区漏洞实验 – Buffer Lab 解析

    原文地址:https://billc.io/2019/05/csapp-cachelab/ 写在前面 这是 CSAPP 官网上的第 4 个实验 buflab,也是学校要求的第三个实验.这个实验比上一个 ...

  5. ubuntu12.04 安装CS:APP Y86模拟器

    下的第一UBUNTU12.04下Y86模拟器的安装:(參考http://archive.cnblogs.com/a/1865627/ 作适当改动) 1.安装bison和flex词法分析工具 sudo ...

  6. 《CS:APP》二进制炸弹实验(phase_1-3)

    <深入理解计算机系统>第三章的bomb lab,拆弹实验:给出一个linux的可执行文件bomb,执行后文件要求分别进行6次输入,每一次输入错误都会导致炸弹爆炸,程序终止.需要通过反汇编来 ...

  7. 深入理解计算机系统 (CS:APP) - 高速缓存实验 Cache Lab 解析

    原文地址:https://billc.io/2019/05/csapp-cachelab/ 这个实验是这学期的第四个实验.作为缓存这一章的配套实验,设计得非常精妙.难度上来讲,相比之前的修改现成文件, ...

  8. CS:APP Chapter 3 程序的机器级表示-读书笔记

    3.1 程序的机器级表示 发展历史 Intel,AMD,ARM 等企业各有又是,CPU 从 8 位发展到 16 位,再到 32 位,近几年发展到 64 位,当下的 CPU 体系被称为 x86-64 体 ...

  9. CS:APP Chapter-6 存储器层次系统-读书笔记

    存储器层次系统 笔记,应该不是一个大而全的文件,笔记应该是提纲挈领,是对思想的汇总浓缩,如果追求详实的内容反而是丢了初心. 计算机是抽象的,它的设计者努力让计算机变得简单,在设计上高度抽象,而计算机的 ...

随机推荐

  1. Linux Centos 下安装软件 三种方式

    1)一种是软件的源代码,您需要自己动手编译它.这种软件安装包通常是用gzip压缩过的tar包(后缀为.tar.gz). 2)另一种是软件的可执行程序,你只要安装它就可以了.这种软件安装包通常被是一个R ...

  2. Code First:Fluent API

    DbContext类有一个OnModelCreating方法,可以在这里配置模型,该方法接收一个类型为DbModelBuilder的建造者,本文介绍的为Data Anotation的等价方法,这些代码 ...

  3. ZOJ 3956 Course Selection System 背包DP

    ZOJ3956 观察数据范围, c的值非常小 只有100 所以c的和也很有限 只有50000 是否可以从这里下手? 对于某一个c的和 我们一定希望h的和最大 才有可能是最终答案. 于是有了类似背包的d ...

  4. 洛谷 P2296 寻找道路 —— bfs

    题目:https://www.luogu.org/problemnew/show/P2296 第一次用 Emacs 对拍,写了半天: 注意那个 is 赋值的地方很容易错,千万别反复赋值: 一道水题写了 ...

  5. oracle中WMSYS.WM_CONCAT函数的版本差异

    昨天在测试的时候发现,开发人员写的一段程序放在开发库中是好的,但是放在测试库中就会有问题.开发人员一直找不到问题的原因在哪里.于是就花了点时间协助开发人员来找问题的根本原因. 通过一些技术手段,定位到 ...

  6. cubism.js

    Cubism.js 是时间序列化的一个D3插件,使用Cubism构建更好的实时指示板,从Graphite,Cube 和其他的资源中拉拉取数据.在GitHub的Apache License上可以获取Cu ...

  7. js滚轮事件需要注意的兼容性问题

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  8. BACnet开发资料与调试工具

    一.开发资料 1.认识BACnet协议 2.BACnet网络讲义: 链接:https://pan.baidu.com/s/1A6OOUxvJe1zIYbockqTEsQ提取码:wz49 二.调试工具 ...

  9. 2017杭电多校第五场Rikka with Subset

    Rikka with Subset Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others ...

  10. ASP.NET 之页面重定向和传值

    在开发 ASP.NET 网站时,经常需要从一个网页重定向(导航)到另一个网页,同时希望能够将信息从源页传递到目标页.例如,如果你正在开发一个保险网站,需要用一个页面来收集基本信息(用户信息.保险产品信 ...