当前位置: 首页 > 后端技术 > Node.js

StanfordProgrammingParadigmLesson2笔记-数据类型在内存中的表示

时间:2023-04-03 11:57:32 Node.js

内存的最小单位是字节,一个字节等于8个位(bit),每个位要么是0,要么是1,即以二进制表示代表。一个字节在内存中的表示是:无符号整数表示无符号二进制转十进制公式:w:二进制位的长度。i:二进制数字从右到左的下标,从0开始计数。w-1:由于i是从0开始计数,所以最后一个下标是w-1。x(i):第i位的值,0或1。2^i:2的i次方。例如:无符号二进制数10010按公式展开:如果这个数在计算机中以1字节存储,则在内存中表示为:小于8位,左边补0。无符号的1字节形式上可以表示2^8=256个不同的数。最大能表示的数是8位二进制数全为1的数,等于255,即求公比为2的几何数列的前8项之和,第一项为1、二进制位求和公式为(2^n)-1综上所述,n位二进制数所能表示的最大数为(2^n)-1,可以表示2^n个不同的数。之所以是2^n个不同的数,是因为它可以表示0~(2^n)-1,从0开始,所以需要+1长度。Char在内存中的表示Char类型用于存储单个字符,在内存中占用1个字节,用8位来表示256个字符。Char类型实际存储的是字符的ASCII码,因为ASCII码是一个整数。所以Char最终成为内存中的8位整数。比如字符A的ASCII码是65,65=2^0+2^6,那么在内存中的表示就是:charch='A';printf("%d",通道);//outputis65ShortinRepresentationinmemoryShort代表一个短整型,一般占用2个字节的内存。它的取值范围是(-2)^15~(2^15)-1包括0。这里的最大值是(2^15)-1,因为short有一个有符号位,最高位(第一个位从左到右)需要用符号来表示,0表示正数,1表示负数。最大值的二进制表示为0111111111111111(16位二进制数),十进制为(2^15)-1。之所以是(2^15)-1,也是前面提到的求和公式((2^n)-1。实现加减法。二进制加减法和十进制一样,把相应的位相加,如果大于1时,会向前移动位。例如0111+1=1000,如果你想将7和-7相加,使结果等于0。根据计算机中二进制的最高位作为符号位的使用,0表示正数,1表示负数。那么7表示为0000111,-7表示为1000111。0000111+1000111按照前面的二进制加法规则就是1001110,结果不是我们想要的0。我们如何将2个二进制数相加得到0?如果要得到0,就需要使用进位。比如11111111(8个1)加1得到100000000(一共9位,左边第一个是1,后面8个0),舍去最左边那个1得到8个0,最后的结果是等于0。将原码逐位取反,与原码相加,即可得到全1的二进制数。比如0000111按位取反就是1111000,两者相加得到11111111,然后再加1得到最后的结果0。整个过程需要3步。我们把最后两步合为一步,即把按位取反和加1结合起来,其实就是在原代码的反码上加1。例如,1111000加1得到1111001。最后两步的组合称为原码取补。最后的1111001称为0000111的补码。正整数的补码就是它自己。负整数的补码是将其对应的正整数二进制码逐位取反,即对原码进行取反后加1。例如正整数7的二进制码为0000111,它的补充是它自己。再比如-7对应的正整数二进制码为0000111,其反码为1111000(将原码逐位取反)。然后加1得到1111001。1111001是-7的补码。我们将1111001和0000111按照二进制加法规则再次相加,正好为0。这里需要注意的是,左边会产生一个溢出位。去掉这个溢出位,结果为0。-1的补码全为1,因为加1后就变成0了。计算机系统用补码来表示二进制码。这样做的好处之一是可以统一处理加减运算。位方式复制将char类型的变量赋值给short类型的变量时,char的8位会放在short的低8位(从右到左第一个字节)。例如:charch='A';//'A'ASCII:65内存表示为01000001shorts=ch;//内存表示为00000000|01000001一种特殊情况是将short-1分配给int变量00000000|00000000|11111111|11111111,因为如果是这样,代表的值就不是-1。所以正确的做法是将所有的1都复制到int中。例如:短s=-1;//内存表示为11111111|11111111int我=s;//内存表示为11111111|11111111|11111111|低八位(从右到左的第一个字节)放在char的唯一字节上。更多字节将被自动删除。例如:短s=65;//内存表示为00000001|01000001字符ch=s;//内存表示为01000001浮点数表示我们已经知道无符号二进制转十进制的公式是:这里的i从0开始,也就是从右数第一个数是2^0。如果我们从一个负整数开始,就会有负整数的幂,然后就会有小数部分。例如,如果有一个16位的二进制数000000011|11000000,用它的前八位表示整数部分,后八位表示小数部分,所以也可以表示000000011.11000000。这样后八位就不再是整数次幂了,而是从左到右每一位都是2^(-1)~2^(-8)。这个数字可以表示为:这是浮点数表示方法之一。这种方法表示的浮点数精度不够,表示的数值范围比较小,所以计算机实际上并没有用这种方法来表示浮点数。下面的方法是在计算机内部实际表示浮点数的方法。我们先来看看十进制的科学记数法。123.45如果用科学计数法表示就是1.2345*10^2。其中1.2345是尾数,10是底数,2是指数。计算机在表示浮点数的时候,也是借用了十进制科学计数法的思想,只不过是以2为底。比如1000.01可以表示为1.00001*2^3,若干次方,小数点会向右移动几个地方。以32位浮点数为例,第一位为符号位S,后面8位为指数位E,最后23位称为尾数位M。计算公式:S:当符号位S为0时就是正数,为1时就是负数。M:尾数部分的取值范围为1≤M<2,取值方式为从左到右,每一位代表2^-1~2^-23,取值则为每一个的表示值bit求和,这里和前面的浮点数表示方法一致,从负整数次方开始。由于尾数的整数部分始终为1,所以这个1可以省略,这样可以多加一位提高精度。E:指数部分减去127是因为偏移量为127,例如0|10000010|11110000000000000000000的各部分为:S:0表示整数。M:11110000000000000000000这里需要加1,因为为了提高小数精度省略了1,所以需要加回去。所以完整的尾数部分应该是1.1111(省略尾随0)。2^0+2^-1+2^-2+2^-3+2^-4=1.9375E:100000102^7+2^1=130分别代入公式:二进制形式:十进制形式:详细过程:1*1.1111*2^(130-127)=>1*1.1111*2^3=>1*1111.1(对于数次幂,小数点会向右移动几位)=>1*(2^3+2^2+2^1+2^0+2^-1)=>1*(8+4+2+1+0.5)=>15.5浮点数和整数的相互赋值当我们赋值浮点数时-将数字和整数相互指向此时并没有直接复制位,而是重新计算新类型中的位模式。例如:inti=5;//内存表示00000000|00000000|00000000|00000101//重新计算5在float中的表示floatf=i;//内存表示0|00000000|)//输出是5.0更精彩一点!!!//2^30inti=1073741824;//内存表示01000000|00000000|00000000|00000000//这里不会重新计算float中的表示,而是直接复制bits。使用float解析方式解析int的内存。floatf=*(float*)&i;//内存意味着0|10000000|00000000000000000000000//1*2^(128-127)*1=2printf("%f",f)//这里输出的是2.0不是会重新计算1073741824在float中的表示,而是直接copy诠释。使用float解析方式解析int的内存。