十进制整数的原码、反码、补码
正数 负数
原码 绝对值对应的二进制表示,最高位为0 绝对值对应的二进制表示,最高位为1
反码 原码一样 绝对值对应的二进制表示,取反
补码 原码一样 绝对值对应的二进制表示,取反加1
八进制和十六进制直接以二进制形式存储,如0xFF为1111 1111。
从计算机存储形式(补码)求表示的十进制,关键是求出补码的原码,从原码转换成十进制
如果补码最高位为0,表示正数,补码的原码就是本身,故直接从补码转换为十进制。
如果补码最高位为1,表示负数,先求补码表示的绝对值(和求补码一样),将补码取反加1得到它的绝对值的二进制形式,将绝对值的二进制形式转换为十进制,最后加上负号。
转换过程中先不管溢出,最后存储的时候舍去溢出的位就可以了。例如,char ch=128;计算机这样存储,128的补码为0 1000 0000,存储的时候舍去溢出位0,所以补码为1000 0000,即变为为-128。1000 0000为何是-128的补码呢?按照上面求负数补码的方法,-128绝对值为128,它的二进制表示为1000 0000,取反加1,得到-128的补码,还是1000 0000。这也说明了为何8位范围为
-128~+127。
float数据的存储
在C++里,实数(float)是用四个字节即三十二位二进制位来存储的。其中有1位符号位,8位指数位和23位有效数字位。实际上有效数字位是24位,因为第
一位有效数字总是"1",不必存储. 有效数字位是一个二进制纯小数。
8位指数位中第一位是符号位,这符号位和一般的符号位不同,它用"1"代表正,用"0"代表负。整个实数的符号位用"1"代表负,"0"代表正。
在这存储实数的四个字节中,将最高地址字节的最高位编号为31,最低地址字节的最低位编号为0,则实数各个部分在这32个二进制位中的分布是这样的:
注意第一位有效数字是不出现在内存中的,它总是"1"。
将一个实数转化为C++实数存储格式的步骤为:
(1)先将这个实数的绝对值化为二进制格式,注意实数的整数部分和小数部分化为二进制的方法是不同的。
(2)将这个二进制格式实数的小数点左移或右移n位,直到小数点移动到第一个有效数字的右边。
(3)从小数点右边第一位开始数出二十三位数字放入第22到第0位。
(4)如果实数是正的,则在第31位放入"0",否则放入"1"。
(5)如果n 是左移得到的,说明指数是正的,第30位放入"1"。如果n是右移得到的或n=0,则第30位放入"0"。
(6)如果n是左移得到的,则将n减去1然后化为二进制,并在左边加"0"补足七位,放入第29到第23位。
如果n是右移得到的或n=0,则将n(不减1)化为二进制后在左边加"0"补足七位,再各位(指这七位)求反,再放入第29到第23位。
或者这么转换:
(5)如果n 是左移得到的,指数部分为127+n,转换成二进制,放入第30到第23位。
(6)如果n是右移得到的, 指数部分为127-n,转换成二进制,放入第30到第23位。
(7)如果n=0即没有移, 指数部分为127,转换成二进制,放入第30到第23位。
(1)先将这个实数的绝对值化为二进制格式,注意实数的整数部分和小数部分化为二进制的方法是不同的。
(2)将这个二进制格式实数的小数点左移或右移n位,直到小数点移动到第一个有效数字的右边。
(3)从小数点右边第一位开始数出二十三位数字放入第22到第0位。
(4)如果实数是正的,则在第31位放入"0",否则放入"1"。
将一个计算机里存储的实数格式转化为通常的十进制的格式的方法如下:
(1)将第22位到第0位的二进制数写出来,在最左边补一位"1",得到二十四位有效数字。将小数点点在最左边那个"1"的右边。
(2)取出第29到第23位所表示的值n。当30位是"0"时将n各位求反。当30位是"1"时将n增1。
(3)将小数点左移n位(当30位是"0"时)或右移n位(当30位是"1"时),得到一个二进制表示的实数。
(4)将这个二进制实数化为十进制,并根据第31位是"0"还是"1"加上正号或负号即可。
double同理,只是double是64位。
符号位 阶码 尾数 长度
float 1 8 23 32
double 1 11 52 64
临时数 1 15 64 80
关键是指数部分
float型:31位是实数符号位,30位是指数符号位(127+n、127-n、127),29—23是指数位,22—0位是有效数字位。// 指数占8位
double型:63位是实数符号位,62位是指数符号位(1023+n、1023-n、1023),61—52是指数位,51—0位是有效数字位。// 主指数占11位
char ch=277在内存中的二进制形式
因为数据在计算机中都是以二进制表示的,编译系统对于不同类型的变量分配不同大小的存贮空间,制定不同的取值范围。比如整型在计算机中的存储用2个字节16位的存储空间,其中的最高位代表符号位的,符号位为0表示的是正数,符号位为1表示为负数,整型数据在内存中以二进制的补码存放。
以10和-10说明正数在内存中的存放形式:
十进制 10 -10
二进制原码 0000000000001010 1000000000001010 //绝对值的原码,把最高位改为1
二进制反码 0000000000001010 1111111111110101 //绝对值的原码取反
二进制补码 0000000000001010 1111111111110110 //绝对值的原码取反加1
其中绝对值的原码指绝对值转换得到的二进制,没有符号位,高位不足就补0,如-128的绝对值的原码是1000 0000,不是01000 0000。
十进制 277
二进制原码 01 0001 0101//溢出两位先不管
二进制反码 01 0001 0101//溢出两位先不管
二进制补码 01 0001 0101//溢出两位先不管
因为计算机以补码存储整数(正负都是),char是8位,所以补码取低8位存储,即0001 0101,补码高位为0,计算机解释为正数,即十进制21。
32796赋值signed char变量类型后在内存中的存储形式
signed char是单字节有符号整数,范围为-128~127。显然32796超出了这个范围。对signed char赋超过变量的值,一般编译器会解释为截取32796的最低字节(因为作为数值类型,一般不考虑字节序问题),也就是32796&0xFF的结果赋值给这个变量(同时可能给出一个溢出/丢失精度的警告)。由于32796二进制表示为1000000000011100,取最低字节也就是低8位是00011100,就是赋值后的值的二进制表示形式,十进制为28。