计算机中基本数据类型的存储结构(unsinged为什么不能修饰double?)

目录

二进制

整数的存储

有符号数

无符号数

计算机以补码来存储整数

浮点数的存储

尾数的规整化

移码

存储结构

字符型的ASCLL码表示

修饰符unsinged


偶然看到一个题目,unsigned为什么不能修饰double,可能也能说出点儿什么,但是总感觉不够清晰,所以找时间从二进制原补码到数据的存储结构,再深入学习一下。

 

二进制

计算机中的数据都是以二进制形式存储的。

为什么是二进制不是八进制十进制呢?因为二进制在现实世界可以用电器元件很容易的实现,并且受磁场等干扰最小。

计算机最底层是用电来控制电子元器件以此表达二进制,电器元件的高电平和低电平分别对应二进制的1和0。

1个元器件表示的一位二进制称为1比特(Bit)或1位,8个元器件也就是8位称为1字节(Byte)。

 

整数的存储

计算机中的整数分为有符号数和无符号数

  • 有符号数

最高位表示符号,剩下的位表示数值。最高位为0表示正数,最高位为1表示负数。

如果用N位来表示整数,那么有符号数的范围为:[-2^(N-1),(2^(N-1))-1]。

用8位来表示有符号整数数,由于第8位用于表示符号,因此,整数的表示范围为[-128,+127]。

  • 无符号数

所有位均用来表示数值,所以只能表示非负数。

如果用N位来表示整数,无符号数的表示范围为[0,(2^N)-1]。

用8位来表示有符号整数数,则无符号数的表示范围为[0,255]。

计算机以补码来存储整数

先要知道原码反码和补码的定义。

  • 原码:在数值前面增加了一位符号位(即最高位为符号位),该位为0表示正数,该位为1表示负数,其余位表示数值的大小。
  • 反码:正数的反码与其原码相同。负数的反码是对其原码逐位取反,但符号位除外。
  • 补码:正数的补码与其原码相同,负数的补码就是对该负数的反码加1。

存储一个整数,要计算其原码,这个很好理解,因为我们要转化成二进制存储。那么反码和补码存在的意义是什么呢?答:为了运算。

假设字长为8位 ,那么原码的运算方式为: 1 - 1 = 1 + ( -1 ) =(00000001) + (10000001) = (10000010) = -2 ,这显然不正确。

原码在两个整数的加法运算中是没有问题的,问题出现在带符号位的负数身上。

 原码无法满足运算要求,因此对除符号位外的其余各位逐位取反就产生了反码。反码的取值空间和原码相同且一一对应。

下面是反码的减法运算: 1 - 1 = 1 + ( -1 )= (00000001) + (11111110) = (11111111) = ( -0 )  没问题。

 1 – 2 = 1 + ( -2 ) = (00000001) + (11111101) = (11111110) = ( -1 )  正确。

反码的问题出现在(+0)和(-0)上,因为在人们的计算概念中零是没有正负之分的

再来看补码的加减运算如下: 1 - 1 = 1 + (-1) = (00000001) + (11111111) = (00000000) = 0 正确。 1 – 2 = 1 + (-2) = (00000001) + (11111110) = (11111111) = ( -1 )  正确。

总结补码的设计目的是: 

  • 使符号位能与有效数值部分一起参加运算,从而简化运算规则。
  • 使减法运算转换为加法运算,进一步简化计算机中运算器的线路设计。 
  • 此外,在补码中用-128代替了-0,所以没有+0和-0之分,符合常理,所以补码的表示范围为: -128~0~127共256个。

有符号的整数的存储结构

例如:int占4个字节,一共32位,除去符号位,剩下31位表示数值。其范围是-2^31 ~ 2^31-1,即-2147483648 ~ 2147483647。

 

浮点数的存储

浮点数的存储是以科学计数法为思想指导的。

在数学中,任何一个实数可以写成科学计数法的形式,X = a × 10^E  (其中 1<=a<10, a和E都是有符号的)

我们把十进制的科学表示法的式子对应改写成二进制的形式  X = (-1)^s × M × 2^E 

  • 符号s   (sign) :把数值的正负符号位单独拿出来用1位表示,当s=0,X为正数;当s=1,X为负数。
  • 阶码E   (exponent) :E用于存储科学计数法中的指数,并且采用移码存储。float类型的阶码是 8 bits,double类型的阶码是 11 bits。
  • 尾数M  (significand) :M是一个二进制小数,符号位已经用s表示了,所以M一定是正的,直接用原码表示即可。 1<=M<2

尾数的规整化

尾数M的取值范围是[1,2),所以M总可以写成1.xxxxxx的形式。IEEE 754规定,在计算机内部保存 M时,默认这个数的第一位总是1,因此可以被舍去,只保存后面的xxxxxx小数部分。这样做可以节省空间,多保留1位有效数字。

所以我们最终保存的只是除去1的有效位。  公式:尾数 = 1+有效位。

移码

阶码E的是用移码表示的。

移码(又叫增码或偏置码)通常用于表示浮点数的阶码,其表示形式与补码相似,只是其符号位用“1”表示正数,用“0”表示负数,数值部分与补码相同。(移码和补码互为相反数)

为什么阶码不用原码或者补码表示而要用移码呢?

浮点数有正有负,其指数也就是阶码是有正有负的,在浮点数运算中,经常需要比较两个阶数的大小,如果直接用补码或者源码,要比较两次符号位:即阶码的符号位和尾数的数符,对机器来说相对麻烦。

用移码的话,可以将阶码增加一个偏移量,使阶码都变为正数,这样可以更方便的比较两个阶码的大小。

比如在32位的float中,其移码是8位。8位有符号数的取值范围是-128~+127,总共有256个值。但是其偏移量是127。如果采用偏置128,在表达+127时会产生上溢(移码11111111被保留),所以在阶码中偏置为(128-1),与此同时,在表达-127时会产生下溢(移码00000000被保留),所以阶码中去掉-127与-128,取值范围为-126~127,总共254个偏移量。

存储结构

在C++中,float的阶码是8位,double的阶码是11位。

  • float一共32位,除去符号位和阶码,32-8-1=23位。所以有效位为23位。表达的尾数是23+1=24位,2^24=16777216。 虽然结果一共8位,但是8位数是表示不完全的,只能表示以1开头的8位数,所以24位可以完全表示所有7位数。由于在计算中会有四舍五入,所以最终结果的精度保持在6位有效数字。
  • 同上,double一共64位,64-11-1=52位。2^53=9007 1992 5474 0992,一共16位,按照上面的分析,完全表达了15位的数字,所以有效数字是14位。可能是因为9007 1992 5474 0992这个数接近10^16,所以也可以说15位有效数字吧。

 

字符型的ASCLL码表示

ASCII码用7位二进制编码(0~127)表示一个字符,总共可以表示128个字符,其中有95个是可显示和打印的字符,包括10个十进制数字(0~9)、52个英文大写和小写字母(A~Z,a~z)、以及若干个运算符和标点符号,除此之外的33个字符是不可显示和打印的控制符号,原先用于控制计算机外围设备的某些工作特性,现在多数已被废弃。

计算机通常用一个字节(8位)来存放一个ASCII字符,字节的低7位表示不同的ASCII字符,而字节的最高1位固定为0。在有些情况下,字节的最高1位也可以用作奇偶校验位以检验错误,或用作西文字符和汉字的区分标识。

 

修饰符unsinged

unsigned可以修饰 int short char等,unsigned 可以使有符号数的第一位符号位也用来表示数据,从而扩大一倍数值范围。

在浮点数规定内存中数据的第一位必须是符号位。因此两者之间是互相矛盾的,所以浮点数不能用unsigned修饰。

 

  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值