【第 2 周】深入理解计算机系统共读心得体会

所在小组:六组
组内昵称:吴彬

1、无符号数编码的定义

2、有符号数编码的定义

3、源码表示

整数使用补码,浮点数使用原码,why?

4、有符号和无符号数字转换


位不变,解释方式改变 golang 也是这套逻辑

测试程序

package main

import "fmt"

func main() {

   var i16 int16 = 128

   var i8 int8

    i8 = int8(i16)

    fmt.Println("i8:", i8)

}

记下两个公式

补码转化无符号

无符号数转补码

5、位扩充和截断

讲的比较啰嗦,核心逻辑就是扩充和截断后,按照指定的码位计算即可

注意程序中的有符号数和无符号数的转换,可能造成程序错误

6、无符号数加法


溢出的情况,相当于就是把最高位丢弃了

溢出检测逻辑 s = x + y s < x or s < y

7、补码加法

检测溢出算法:

x > 0, y > 0, s <=0 正溢出

x <0, y < 0, s >= 0 负溢出

所在小组

第三组

组内昵称

kippa

心得体会

  1. 如何具体理解运算的细致特性?
  • 个人的体会是在自己熟悉的编程语言练习这些运算,尤其是那些可能导致溢出、截断等异常情况的运算。以 go 语言为例,关于无符号数转为补码的表示,go 语言在进行强制类型转换时也有这样的规则;由于 go 语言是强类型语言,不允许类型不一致的数之间的运算,也就导致 go 语言并没有隐式类型转换。
  1. 通过位运算、加法运算提高乘法、除法的效率
  • 乘法、除法都可以转换成位移、加法、减法运算的组合,在大多数机器上,加法、减法、位移所需的指令周期为1,而乘法所需指令周期在 10 个左右,除法所需指令周期在 20-40 个之间,因此这种转换能够提高效率。
  1. IEEE 浮点数表示
  • IEEE 浮点数的表示方法是为了解决二进制多项式表示方法表示精度不足,如1/3这样的分数无法表示,而且在定长位数下,不能同时表示极大数及接近 0 的数。
  • 用类似科学计数的方法表示,这样的表示小数点是浮动的,所以称为浮点数。(相对的,小数点确定的叫做定点数,整数也是一种定点数)

image

S:标志位(1位)
E:阶码(8位),作用是对浮点数加权
F:尾数(23位),这个数有些特别,它的取值范围[1,2)或[0,1),跟E的取值相关

1.所在小组:第三组
2.组内昵称:wyhqaq
3.心得体会
第二章内容之前考研的时候费劲头脑过了好几遍,这次就温故一下。

  • 整数表示

    • C语言定义了很多种整数表示类型。而C、C++语言可以支持有符号数和无符号数,Java只支持有符号数。
    • 整数有在计算机中有几种编码方式,分为原码、补码以及反码。而现代的计算机通常使用补码来进行编码
  • 整数运算

    • 具体的各种编码对应的计算法则要能熟悉,虽然不用记得,但是看到了要能马上理解。

    在程序设计以及整数类型选取中,一定要注意几个问题,第一是类型转换中,精度丢失。比如int64–>int32。第二就是数值溢出问题,最简单的比如Math.max+1会导出结果溢出,出现一些莫名的bug。

  • 浮点数

    • IEEE754标准规定了浮点数及其运算的标准,正因为有了标准,厂商们才不会割裂开来,各自搞各自的一套,也增加了程序的可移植性。
    • 因为计算机是使用2进制,所以二进制并不能表示每一个小数,比如1/3,只能采取一种无限逼近的近似值,这就导致了浮点数是有误差的,这点一定要注意。
    • 浮点数计算比整数计算复杂很多,现代的科学计算需要实现很高的计算精度,所以评价超级计算机性能强弱的一个重要标准就是浮点运算速度。

    程序中使用浮点数一定要注意的一个问题就是,浮点数不是精确的数,在各种算数计算中都可能会出现精度丢失的现象。

1.所在小组:第7组
2.组内昵称:李佳
3.心得体会
整数表示

  • 负数的补码,取反加一

整数运算

  • 复习了一下cpu实现中加法器,乘法器的实现,半加器输入为两个需要相加的一位二进制数,输出为是否进位和结果,全加器由两个半加器组成,输入多了一个低位的进位.
    乘法器本质还是加法器的组合,利用布斯算法减少运算,除法器的实现有三个关键寄存器,除数寄存器,余数寄存器,商数寄存器,通过循环的减法来实现,所以能用加法和乘法尽量用,减少使用除法.
    多利用移位运算可以提高效率,但是可能会降低代码可读性,根据个人进行取舍例如,x*7等同于(x>>3)-x.

浮点数

  • 浮点数不准确
  • 舍入向偶数,向上或向下取的概率都为50%,可以避免统计偏差

所在小组

第六组

组内昵称

慎思明辨笃行

你的心得体会

https://zsy619.github.io/csapp/20200921到20200927日读书汇总/

整数表示

用位来编码整数

- 函数:二进制转补码、二进制转无符号数、无符号数转二进制、无符号转补码、补码转二进制、补码转无符号数
- 常数:最小补码值、最大补码值、最大无符号数
- 操作:补码加法、无符号数加法、补码乘法、无符号数乘法、补码取反、无符号数取反

整型数据类型

32位与64位机器取值范围不同
大多数64位机器使用8个字节表示,比32位机器上使用4个字节表示取值范围大
建议安装64位的操作系统
不同语言对有符号与无符号支持也不同,如c支持有符号与无符号数。而java只支持有符号数。

无符号数编码

采用向量表示(定义)法
最小值0,最大值二的N次方减一
无符号数编码具有唯一性
双映射,了解反函数

补码编码

有符号数采用补码进行表示
负权:最高位表示,1表示负、0表示正 → 所以负数比正数大1
通过补码,可以了解有符号数存储规则
补码编码的唯一性,双射
补码范围不对称:|TMin| = |TMax| + 1
UMax = 2TMax + 1
long类型:不同机器有不同的取值范围
反码、原码

有符号数与无符号数转换

  • 以后要加强阅读

扩展一个数字的位表示

无符号数的零扩展
补码数的符号扩展

截断数字

截断无符号数

整数运算

无符号加法

  • 无限精度的运算:lisp语言
  • 固定精度的运算:溢出

补码加法

  • 正溢出
  • 负溢出

补码的非

  • 要深入了解概念

无符号乘法

  • 要深入了解概念

补码乘法

  • 要深入了解概念

浮点数

二进制小数

  • 充分理解计算机小数表示存储

IEEE浮点表示法

  • 还需精读(概念、参数含义)
  • 格式化的值
  • 非格式化的值
  • 特殊值

舍入

浮点溢出

  • 精彩案例:浮点溢出的高昂代价
    • 火箭发射失败
    • 原因:类型间转换失误

1.所在小组:第七组
2.组内昵称:陈盛华
3.心得体会

  • 了解C语言的历史。安装C语言环境中,发现C89后面的数字代表89年,C99和C11同理,学习的东西都是几十年前,
    是现代计算机最基础的知识也是最核心的东西,发现自己一直在高层上开发软件,就没想到底层如此复杂和精妙。

  • 记住一些技巧,
    十六进制到二进制的转换,可以记忆A(1010),C(1100),E(1111),以后可以方便转换。
    long,char在用32位和64位的方法编译出来占用的字节数不用,分别是4字节(32位编译),8字节(64位编译)。
    分清楚位运算(&)和逻辑运算(&&)的区别,前者是将两个二进制数一起做算数运算,后者是比较逻辑运算符两边的布尔值。
    二进制的移位,左移一位为原数值数字乘以2,右移一位为除以2。

  • 认识到整数编码的数学表示。所有科学的底层都是数学,这句话诚不欺我。
    从人们常用的正整数(无符号)开始,已经可以解决大部分的问题,但是受限于个别情况和计算机位数限制,
    出现了负数和溢出(有符号)。而这个时候,就需要一套数学可证明的系统来解决问题。

  • 了解浮点数的定义:某一位的(数)乘以(进制数下标)的(次幂),最后所有数相加。

    例子,12.34(十进制数),1*10^1  +  2*10^0  +  3*10^-1  + 4*10^-2
         101.01(二进制数),1*2^2  +  0*2^1   +  1*2^0    + 0*2^-1  + 1*2^-2
    
  • 舍入。对浮点数非常总要的概念,因为存在计算机无法在二进制精确表示的浮点数。
    例子,1/5=0.2,这个0.2数值,无法在二进制位上精确表示,只能通过扩大(二进制的小数位)来近似。
    例如0.00110011(二进制)表示0.19921875(十进制)近似表示0.2(十进制)。

  • 学习这一章节,回忆起一句话,如果觉得现在很困难,那可能是在前面某个地方缺失了,需要补充起来。

所在小组:六组
组内昵称:杨凯伟

整数编码

  • 无符号数的编码

向量 x 中的每一个元素表示一个二进制位,其中每一位取值为0或1。即我们理解的二进制转十进制的方法。

B2U_w(x) = \sum^{w-1}_{i=0} x_i2_i = x_{w-1} \cdot 2^{w-1} + x_{w-2} \cdot 2^{w-2} + ...+ x_0 \cdot 2^0
  • 有符号数的编码

有符号数的最高有效位即为符号位,它的权重为 -2^{w-1}, 1时为负,0时为非负。由于 0 是非负数,这就导致能表示的整数比负数少一个。

B2U_w(x) = - x_{w-1}2^{w-1} + \sum^{w-1}_{i=0} x_i2_i = - x_{w-1}2^{w-1} + x_{w-2} \cdot 2^{w-2} + x_{w-2} \cdot 2^{w-2} + ...+ x_0 \cdot 2^0

如:
B2T_4([1111]) = -1 \cdot 2^3 + 1 \cdot 2^2 + 1 \cdot 2^1 + 1 \cdot 2^0 = -8 + 4 + 2+ 1 = -1

值得注意的是 -1 都是补码表示都是一个全1的串,然而这无符号数的最大值的表示一致。

  • 正数用原码负数用补码?

正数用原码负数用补码。
计算机都用补码存储数据。

这两个说法都没有问题,因为正数的 原码 = 补码。

  • 为啥负数要用补码?

原因之一就是方便计算,如$165 + (-165) = 0$ 如果使用原码进行计算,需要单独把符号位拿出来,再做减法运算,而把符号位区分出来是需要额外的硬件电路支撑的,这很不方便。

如果使用补码,如下所示(这里按照16位进行举例):

0000 0000 1010 0101 + 1111 1111 0101 1011=0000 0000 0000 0000;

使用补码参与运算后,无需再管符号位,可以让符号位直接参与运算。

有符号数和无符号数的转换

原则:保持位值不变,只改变解释这些位的方式
先来看 C 语言中的强制转换:

short int v = -12345;
unsigned short uv = (unsigned short) v;
printf("v = %d, uv = %u\n", v, uv)

在采用补码的机器上(基本上计算机都采用补码存储信息)输出:v = -12345, uv=53191
原因:

-12345: 1100 1111 1100 0111
53191:  1100 1111 1100 0111
  • 有符号数转无符号数
    x >= 0 时结果不变,x < 0时结果为 x+2^w
  • 无符号数转有符号数
    对于小的数($<= TMax_w$)时结果不变,对于大的数($> TMax_w$)时,数字将被转换为一个负数。结果为 $u-2^w$。

在 C 语言中,当执行一个运算时,如果它的一个运算书是有符号的而另一个是无符号的,那么 C 语言会隐式地将有符号参数强制类型转换为无符号数。

  • 将一个较小的数据类型转换为一个较大的数据类型

    • 无符号数
      零扩展(简单的在开头补0),可以保持数值不变。
    • 有符号数
      需要执行符号位扩展,这个符号位就是最高位。当为非负数时,最高位是 0,此时扩展的数位补 0 即可。当为负数时,最高位时 1,此时扩展的数位补 1 即可。
  • 将一个较大的数据类型转换为一个较小的数据类型
    丢弃多出的高位。

IEEE浮点数

讨论占用32位机器上的IEEE 754标准的单精度浮点数格式

IEEE754 标准把 float 型的32个坑做了如下划分:
Clipboard_2020-09-24-11-23-47
其中包含了1位符号位S,8位阶码E和23位尾数M。

S: 符号位,0表示正数,1表示负数
E: E=e(实际指数)+127(Bais,值为 $2^{k-1} -1$)
M: 真正的有效位数包括二进制点右边的23个小数位和值为1 的隐式前导位(二进制点的左边),除非指数存储为全零。因此,有效格式中仅出现有效数字的23个小数位,但总精度为24位

IEEE754 标准做了这样的规定:当尾数(小数)不为0时,尾数域的最高有效位为1,即 ${\displaystyle (1.x_{1}x_{2}…x_{23})_{2}\times 2^{e}}$,规格化之后我们只需要存储一个尾数(即小数部分(frac),整数部分恒为1)和指数部分(exp)。

  • 为什么要用指数加上127,才是阶码E,而不是直接用指数存进去?

我们希望存储到机器里的阶码永远都是正值,因为我们不希望再浪费一个坑去保存阶码的正负号,于是乎,干脆把指数加上127,而指数能取到的最小值就是-127,这样就可以保证阶码 E 永远都是正数啦,我们就不用再考虑指数正负号的问题了。

  • 精度问题
    十进制小数转化为二进制小数时,小数部分超过了 23 位就会发生精度丢失(舍入)。 默认是舍入到最接近的值,如果“舍”和“入”一样接近,那么取结果为偶数的选择。
    浮点数计算时可能还会再次丢失精度。

所在小组:第一组

组内昵称:文弱书生

心得体会:

本周的读书内容为第二章,信息表示。内容比较难,理解比较粗浅

所学内容:

1.最小的可寻址的内存单位 = 1字节 = 8位

2.内存的每个字节都由一个唯一的数字来标识,称为它的地址,所有可能地址的集合称为虚拟地址空间

3.16进制表示法 eg.0x4FFC

4.16进制、二进制、十进制之间的转换方法

| 十六进制数字 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | A | B | C | D | E | F |

| :—: | :—: | :—: | :—: | :—: | :—: | :—: | :—: | :—: | :—: | :—: | :—: | :—: | :—: | :—: | :—: | :—: |

| 十进制值 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |

| 二进制值 | 0000 | 0001 | 0010 | 0011 | 0100 | 0101 | 0110 | 0111 | 1000 | 1001 | 1010 | 1011 | 1100 | 1101 | 1110 | 1111 |

5.数据类型大小,机器类型不同,数据所占用的字节大小也不同

6.小端法:最低有效字节在最前面的方式,大端法:最高有效字节在最前面的方式

7.逻辑右移和算术右移的区别

逻辑右移:在左端补 k 个 0,[0,…,0,xw-1,xw-2,…,xk]

算术右移:在左端补 k 个最高有效位的值,[xw-1,…,xw-1,xw-1,xw-2,…,xk]

8.整数的表示法:

无符号:在0~2w - 1之间的每一个整数都可以映射为一个唯一的长度为w的位模式

有符号:补码编码,将字的最高有效位解释为负权。

整数的运算

9.浮点数的表示法:

IEEE标准 V = (-1)s * M * 2E

10.大多数机器对整数使用补码编码,而对浮点数使用IEEE标准754编码。

所在小组

第6组

组内昵称

蒋权

心得与体会

持续到第二周了,内容有些偏底层,内容越来越难啃,但是我会坚持下去的,不懂得慢慢啃,没看懂得后面回过头来再看,所谓温故而知新——只有真正去做才体会到其中含义。 其中有些名词和慨念还是挺有意思的,特此记录一下。

  • 内存中所有的对象都有地址,而这些地址就是字节序列,这些字节序列是连续的,而对象的地址为所使用字节中最小的地址。

  • 在内存中按照从最低有效字节到最高有效字节的顺序存储对象——有效字节在最前面的方式,称为小端法(little endian)。

  • 按照从最高有效字节到最低有效字节的顺序存储——有效字节在最前面的方式,称为大端法(big endian)。

  • 感觉下来,这章节对于数学计算和逻辑运算还是右一个比较基础的要求,当然,慢慢去体会和研究,我相信会攻克难关的。

  • 开头很大一部分都在做练习题,对于不是计算机专业的我来说,确实很难,后面遇到新的问题会在此出补充和添加。继续加油。

所在小组:第一组
组内昵称:蔡源彬
心得体会:

  • 原码、反码、补码是计算机编码的三种方式。反码是为了解决减法问题而产生的,但是反码表示0有两种编码方式,于是便诞生了补码,使得0只有一个编码方式,而且扩大了表示范围,从[-127, 127]变成[-128, 127]。

  • 符号位正数位0,负数为1,正数的原反补是一致的,负数的反码等于原码符号位不变其余按位取反,补码是在反码的基础上+1。

  • 算数运算溢出溢出是指完整的整数结果不能放到数据类型的字长限制中去。

  • 浮点运算只能近似地表示实数运算。

总结:第二章比较多的数学运算,看得没有太多体会,第三章情况应该会有所不同。

所在小组

第二组

组内昵称

Joey

你的心得体会

这章讨论了在计算机中的数字的表示方法,个人认为实际上就是基于位模式的数据结构。这些表示数字的数据结构都是精心设计过,并且与CPU的运算单元的设计(比如加法器)有高度配合的。

整数的表示和运算

  1. 在本科的数电课上就学习过补码的概念,当时只是知其然而不知其所以然。深入读了《CSAPP》的对应章节后,才发现有符号数和无符号数的加法可以使用同一个加法器逻辑。

  2. 在x86汇编语言里,有符号和无符号数的加法都是同一条指令,也就是说CPU是一视同仁的,只有使用者知道当前进行的有符号还是无符号运算,如果想获取当前运算的某些状态(进位、溢出等),需要使用者根据当前进行的运算的类型,去获取EFLAGS寄存器中相应的标志位。

  3. 在跟着书上的式子推导公式的过程中(比如截断、溢出等),深刻感受到数学思维的重要性,有时候是反直觉的,但是可以一步一步有理有据的推导出正确结果。

浮点的表示和运算

  1. 浮点数本质上也是基于位模式的数据结构,主要解决的是使用有限的二进制位来表示十进制小数的问题。

  2. 由于进制限制,多数有限位数的十进制数无法用有限位数的二进制数来表示,所以浮点数在数轴上的表示就是一些点的集合。并且这些浮点在数轴上的分布是不均匀的,数的绝对值越大,点的分布越稀疏。如果把一个无法被准确表示的十进制小数赋值给浮点数,就会被舍入到能准确表示的小数上。

  3. 由于浮点数的设计,非规格化的情况下,为0附近的小数提供了额外的精度。1~2里面的所有浮点数,就跟2~4里面的所有浮点数一样多(引自知乎轮子哥)。所以使用浮点数表示接近0的数要比表示较大数字要精确得多。

最后

  1. 这章确实有难度,公式推导一环扣一环,需要有耐心。

  2. c/cpp中没有对整数溢出和回绕的debug模式下的动态识别支持,如果要写的代码是涉及到大量的数值计算,确实够经验不太丰富的coder喝一壶的。

所在小组: 第二组
组内昵称:可可
心得体会:

第二章,一个特别重要又那么“无用”的章节。第二章加起来前前后后读了有两三次吧,今天整理思绪的时候发现还是没有留下什么(我学到了整数表示和运算,学到了浮点数的表示和运算,但是仍然发现记不住)。

DDIA的第一章有这么一句话

The Internet was done so well that most people think of it as a natural resource like Pacific Ocean, rather than something that was man-made. When was the last tine a technology with a scale like that was so error-free.

该章节整体给我的感觉就像上面那句话那样,除了几个常见的精度失真,数字溢出之外,我们几乎不用关注底层数据表示,上大学时候经常背的晕头转向的大小端也从来不会影响到工作中的搬砖。a/2还是a >> 2的性能差距在数据密集应用以及水平扩容的架构下先的那么微不足道。

内心OS完毕,第二章除了学到一些底层实现以外。

我学到了补码设计的神奇之处

  1. 正数之间、负数之间可以直接比较
  2. 正负数可以通过符号位比较
  3. i++ 的操作在正负之间很是适配

也学到了浮点数的表示转换,浮点数中所谓的格式化和非格式是不是可以为了便于我们理解引出来的概念,对于计算机这些机器码都是一样的,对于计算机来说这些是平滑的,可以直接比较的。对于计算机来说只要是浮点数他们的公式都是一致的。这块如果我们忽略所谓的格式化,非格式化,站在计算机的角度,就一个公式 是不是更好理解一些,毕竟我们没有必要真正的算出具体的数值。

TODO

  1. 精读失真举例

小结

正如最开始说的,计算机优秀的封装是我们渐渐的忽略了这些细节,架构的发展渐渐的使得性能不再是瓶颈。但唯有思想和灵魂不灭,代代传承,以后的设计也许可以借鉴些许。

此外该节的阅读可以认为我们把目录印在脑子里,一旦某天遇到问题,我们可以快速找到资料,虽然不能直接定位问题,但也不至于无从小手。

共勉

所在小组:第6组
组内昵称:undefined
读书笔记:

关于补码

正数的补码就是其本身,负数的补码就是在其原码的基础上,符号位不变,取反后加一。
补码的设计核心可以使符号位能与有效值部分一起参加运算,从而简化运算规则;
让减法运算转换为加法运算,进一步简化计算机中运算器的线路设计。

关于反码

反码解决了负数加法运算问题,将减法运算转换为加法运算,从而简化运算规则;
其作用有:在加、减、乘、除等运算过程中用作中间数;
实现某些特定功能的逻辑设计上经常要用到,特别是在判断语句,循环语句等需要做出判断的时候。

针对浮点数

相同字长的情况下,浮点数所能表示的范围远远大于整数;当然在精度方面,浮点数不如整数,浮点数的运算比整数复杂
因为既要做尾数的运算还要做阶码的运算,运算结果也需要规格化。其中还存在一个规格化和非规格化的区分。
所以在针对浮点数计算时,需要小心处理。避免规格化处理后导致丢失数据

大小端概念

本章节中,大小端的概念在各个存储系统中都有兼容逻辑,针对不同操作系统,需要考虑不一样的逻辑。而在网络设计中,其实并没有特别多的处理,或许是信息化后开始标准化的原因吧。

所在小组:
第七组

组内昵称:
Shawn

心得体会:

数字是以补码的形式存储在计算机之中。补码的第一位表示符号位,对于一个w位的数字而言,其符号位的权重为-2^w。符号位的值为1时表示数字为负数,符号位的值为0时表示该数字为非负数(注意不是正数)。正是由于0值的符号位也是0的原因,对于任何一个数字而言,其正值和负值的补码表示并不是对称的,不能直接通过取反值来得到。对于负数转换为正数,需要安位取反之后再加上1。反值,从正数转换为负数则是先减去1再按位取反。

作为计算机标准的数字表示方式,补码最大的好处就是:计算时,不用区分符号位和数字位,它们全部可以按照普通数字位的计算方式进行计算。

谈到计算,也不得不提到,计算机计算和数学计算实际上是两个概念。以加法为例,两个w位的数字进行求和运算,其结果可能会有w+1位。在数学计算中,这没有任何问题。但是在计算机计算中,多余的位会被舍弃。因此,计算机计算中,两个正数求和得到的结果可能是负数,两个负数求和的结果也可能会是正数。

所在小组

第六组

组内昵称

利健锋

你的心得体会

  1. 正数溢出的灾难
  • 假设你的积分消费额度比较大,大到可以在消费时扣负积分的时候,就要被刷积分了
  • Go 的 math 包你值得拥有,已解决基础数值的范围边界,只要在编码时做好边界校验
  1. 浮点数精度丢失
  • 听说过一个故事,某电商程序员在交易时将精度丢失部分转移到了自己的账户上,成功年薪百万
  • 普遍解决方案时使用 Decimal
  1. 不单单是知识点可以分多阶段阅读,作业也是,可以按照不同阶段的阅读理解来再次完成。

疑问点

什么时候是逻辑右移?什么时候是算术右移?

所在小组:第二组
组内昵称:梁广超
心得体会:
2.2至2.5节,主要介绍了整数的表示,原码与补码的转化,整数的运算以及浮点数。

 1. 整数的表示
  C 语言的整型数据类型分为 典型取值范围与标准取值范围;
  典型取值范围的正负数不对称,但是按照机器字长部分数据类型分为32与64位(long),标准取值范围正负数对称;
 2. 原码补码转化
    无符号数与有符号数的转换 是从位上面考虑的,既转化之后会出现不相等的情况
3.扩展一个数字的位表示
  无符号数高位补零
  有符号数高位补1
4.截断无符号数
  丢弃高位,十进制数对2**k 取模
5.截断补码
  丢弃高位,再将最高位转化成符号位,十进制也是取模

截屏2020-09-27 下午7.12.35
n为保留的位数
求[-B]补 -> 负数的补码是在原码的基础上除符号位外其余位取反后+1
6.浮点数
浮点数的公式分为 符号,尾数,以及阶码,阶码的位模式是使用偏移量表示
7.取舍
取舍分为向上、向下以及向偶数舍入

所在小组

第六组

组内昵称

钟荣荣

心得体会

这一章比想象中难,大部分知识原理虽然简单,但是只看第一遍还是不能充分理解,还得二刷三刷并做一做练习题。
1.整数的表示:关于正整数和零的表示很容易理解,现代计算机普遍采用的负整数表示与我想象中的不一样,我以为的负整数表示方式是原码,这也是一个最直观的表示方式。而补码有点反直觉,但理解其原理之后能感觉到这种方式的巧妙。对于整数的表示方式的知识,日常开发中使用静态语言和设计数据库的时候常常接触到,以前没有仔细考虑过不同数据类型对代码造成的影响。
2.整数的运算:关于整数的运算原理还比较容易理解,这部分的关键在于各种运算可能带来的溢出,溢出的原理也很容易懂,但是实际应用中常常因为考虑不周而出bug。
3.浮点数:浮点数的精度问题一直以来是工作中特别是支付业务中必须要考虑的问题,在十进制中能精确表示的数,转换为二进制却只能表示为近似值。理解浮点数的精度的取舍规则有助于理解浮点数在计算机中的特性。
这章的知识点中穿插了很多练习题都没有动笔去算,感觉读得有点囫囵吞枣了,国庆放长假还得再刷一遍,并且把练习题做了。

CSAPP共读心得体会 - 第二周

  1. 所在小组:第三组
  2. 组内名称:hhhhhhe
  3. 心得体会:
  • 整数

整数在计算机中分为有符号和无符号,有符号的数可以表示正负数和0,无符号的数只能表示非负数。

  1. 计算机如何表示非负数?

    通过位编码表示,二进制中每一位数表示2^x是否有值

  2. 计算机如何表示负数?

    补码方式(大多数计算机均采用这种方式):

    使用二进制整数的最高位表示负权

    反码方式:

    使用二进制整数的最高位表示符号位,0位正,1为负,

    原码方式:

    原码使用二进制整数的最高位表示符号位,0为正,1为负,8bit可以表示的范围为-127~127。原码对人类而言简单直观,但是对于计算机而言,需要判断最高位是0还是1需要更加复杂的电路设计。

  3. 整数运算

    有符号与无符号的转换,极易出现正反溢出,需要对转换的数学原理和公式了然于胸,才不会在编码中出现因为溢出导致的bug

  • 浮点数
  1. 使用IEEE标准754编码
  • 难的离谱,向所有计算机科学家致敬

所在小组

第五组

组内昵称

张学广

心得体会

第二章开启了计算机基础的学习,不仅为我们介绍了不同类型信息是如何在计算机中存储的,也介绍了他们之间的运算,包括算术运算、位运算、逻辑运算等。其中整数运算以及浮点数为我们详细展开。

整数运算是为了介绍原码、反码和补码,为我们展现计算机是如何进行运算的,之后的浮点数介绍展现了浮点数在计算机中不同的存储以及运算逻辑。

这些知识都是大学学习过的,现在看来有不同的感受,第一点是对类型转换的警觉,显示的类型转换我们都可以洞察到,但是隐式的还是会发生很多奇怪的问题的,这需要我们在写代码的时候有所警觉。第二点是对运算效率的窥探,很多时候位运算可以解决我们很多复杂的运算,提升运算效率,大型项目的效率瓶颈有时候就在这些细微的小地方。

所在小组

第七组

组内昵称

KAI

你的心得体会

公式的来源经过数学的严格推导的,知其然知其所以然!

整数:

  1. 各种编码,以及编码之间的转换。以及有符号和无符号之间的转换。以及隐式强制类型转换和无符号数据类型转换可能带来的危险性,写代码的时候,应该会留意些了。

  2. 整数溢出以及正负溢出所带来的灾难。

  3. 检测正负溢出算法。

    x > 0, y > 0, s <= 0 正溢出
    x < 0, y < 0, s >= 0 负溢出
    

浮点数:

  1. 二进制小数的计算,规格化的值。
  2. 特殊值及其被引入的原因。

编程中需要警惕的:

  1. 尽管 Go 提供了将浮点数转化为整型的方法,但是要尽量避免这么做!
  2. 分析代码,必要时需要站在机器角度理解