整数、浮点数在计算机中的存储,-128二进制怎么表示,

1 计算机底层存储数据的基本原理

        计算机要处理的信息是多种多样的,如数字、文字、符号、图形、音频、视频等,这些信息在人们的眼里是不同的。但对于计算机来说,它们在内存中都是一样的,都是以二进制的形式来表示。要想学习编程,就必须了解二进制,它是计算机处理数据的基础。

        内存条是一个非常精密的部件,包含了上亿个电子元器件,它们很小,达到了纳米级别。这些元器件,实际上就是电路;电路的电压会变化,要么是 0V,要么是 5V,只有这两种电压。5V 是通电,用1来表示,0V 是断电,用0来表示。所以,一个元器件有2种状态,0 或者 1。我们通过电路来控制这些元器件的通断电,会得到很多0、1的组合。例如,8个元器件有 28=256 种不同的组合,16个元器件有 216=65536 种不同的组合。虽然一个元器件只能表示2个数值,但是多个结合起来就可以表示很多数值了。

        我们可以给每一种组合赋予特定的含义,例如,可以分别用 1101000、00011100、11111111、00000000、01010101、10101010 来表示 C、语、言、中、文、网 这几个字,那么结合起来 1101000 00011100 11111111 00000000 01010101 10101010 就表示”C语言中文网“。一般情况下我们不一个一个的使用元器件,而是将8个元器件看做一个单位,即使表示很小的数,例如 1,也需要8个,也就是 00000001。1个元器件称为1比特(Bit)或1位,8个元器件称为1字节(Byte),那么16个元器件就是2Byte,32个就是4Byte,以此类推。我们平时使用计算机时,通常只会设计到 KB、MB、GB、TB 这几个单位,PB 和 EB 这两个高级单位一般在大数据处理过程中才会用到。

  • 1Byte = 8 Bit
  • 1KB = 1024Byte = 2^10Byte
  • 1MB = 1024KB = 2^20Byte
  • 1GB = 1024MB = 2^30Byte
  • 1TB = 1024GB = 2^40Byte
  • 1PB = 1024TB = 2^50Byte
  • 1EB = 1024PB = 2^60Byte

        所以,在内存中没有abc这样的字符,也没有gif、jpg这样的图片,只有0和1两个数字,计算机也只认识0和1。所以,计算机使用二进制,而不是我们熟悉的十进制,写入内存中的数据,都会被转换成0和1的组合。

2 整数的存储

2.1 整数的基本概念

        大家知道,整数包括负数,零,和正数。计算机中的整数分为有符号数和无符号数。

  • 有符号数:最高位表示符号,即最高位为0,表示正数,最高位为1,表示负数。如果用N位来表示整数,那么有符号数的范围为:[-2(N-1),(2(N-1))-1]。用8位来表示有符号整数数,由于第8位用于表示了符号,因此,整数的表示范围为[-128,+127]。
  • 无符号数:表示非负数,整个位数都用来表示整数的值。如果用N位来表示整数,无符号数的表示范围为[0,(2^N)-1]。用8位来表示有符号整数数,则无符号数的表示范围为[0,255]。

2.2 整数的编码方式

整数的编码分为原码、反码、和补码。计算里使用的是补码的存储方式。它们的定义如下:

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

-128的二进制表示

今天看到8位2进制表示的范围是-128-127。原来没有想过为什么是这个范围,仔细一想,奇怪呀,-128是怎么表示的。127是0111 1111,而-128为什么是1000 0000呢,这不是-0吗?于是就有了下文要说的一些内容。
STEP1
为了从根本上明白-128为什么是1000 0000,我们需要从一个叫【模】的东西讲起,并且把你原来关于原码补码反码的一些东西都暂时忘掉。
‘模’是什么,简单来讲就是一个范围内的极限。举一个经典的例子,我们日常生活中的12个刻度的时钟,它表示0-12小时。假设它现在处于2的位置,如果你要让它减少4个小时,到10的位置,你会怎么做?把时钟顺时钟按照3,4,5的方向转8个小时?还是按照1,12,11的方向逆时针转动转4个小时?这2者的结果都是一样的,让时钟到了10的位置。
我们来看一下,一个是拨了8小时,一个是拨了4小时,8+4=12,12-8=4。一个时钟一圈12个小时,也就是说最大的表示上限是12。往前8小时和往后12-8=4小时效果是一样的。而这个12就是所谓的【模】。在模的范围内, +某个数X +模-|x| 的效果是一样的。举个例子
十进制的数,20 和 80 ,两者相加是100,100为模,那么我们50-20 =30,与50+80=130,如果去除百位上的数字,在模(100)的范围内,是不是都是30,结果相同。也就是X -Y = X+(模-|Y|)。
没错吧。不过上面我们是 大-小,如果是 小-大呢?怎么表示。

STEP2
还是20这个数字,按照原来是思路10-20=-10,10+(100-20)=90,不相等了对吧,这可怎么办?我们伟大的前人想到了一个办法,将负数用它的绝对值的补数表示也就是“模-|负数x|” 表示。也就是【模】-|负数|,100-|-10|=90;这样是不是就很完美了,可以表示负数了!
不过这里还存在一个问题,既然-10可以用90表示了,那么原本的90该怎么表示呢?很直接,模范围内一分为二,0-49表示正数,50-99表示负数。

STEP3
好了,回到-128上。对于8进制的2进制数,模是2的八次,256。如果抛开负数,我们能表示0 ~ 255没问题吧。现在我们把0 ~ 255进行对半分,0 ~ 127以及128 ~ 255.像上面所说的100一样,,0 ~ 127表示正数,128 ~ 255表示负数补数的负值,也就是说128 ~ 255为【模】-|负数x|后的值,256-|-128|=128,256-|-1|=255。到这里你应该明白为什么八位2进制数能够表示的范围是-128 ~ 127了吧。 需要注意的是,以上这些运算都需要在-128~127的范围内,这里所谓的负数的二进制码就是它们的补码,不然会产生溢出,也就不符合这个逻辑了。
接下来我们再看看为什么-128的表示是1000 0000。我们是用256-|-128|=128去表示-128的,128的补码就是1000 0000,这也就是为什么-128是用1000 0000表示了。
最后说一下计算机是怎么求这个补码的。负数在计算机中都是用补码存储表示的,当我们输入一个负数的时候,计算机还是要用 模-绝对值来求对应的补码,可是计算机只有加法,为了求这个对应的补码,计算机会将原码首位不变,其余位取反然后加1来求这个补码,-128没有原码和反码,只有补码。换个角度考虑,负数的补码就是其绝对值源码+1,-128就是128的原码10000000求反0111 1111 +1 -》1000 0000

因为计算机是以补码来存储整数的,所以补码就显得很重要。那么如何计算整数的补码呢?下面以具体例子来说明。

100 的补码:01100100
0 的补码:0
-100 的补码:绝对值:01100100 -->取反加1:10011011+1 -->10011100
1 的补码:00000001
-1 的补码:绝对值:00000001 -->取反加1:111111110+1 -->11111111
127 的补码:01111111
-128 的补码:绝对值:10000000 -->取反加1:01111111+1 -->10000000 在计算机系统中,数值一律用补码来表示(存储)。
在这里插入图片描述
 从定义可以看出,正数的补码,反码,原码相同。0的补码就是本身。那么负数的原码和补码如何转换呢?==已知一个负数求补码方法:绝对值原码按位求反加1。已知负数补码求负数方法:符号位不变,其他位按位求反加1。==对于8位整数来说,补码的表示范围为[-128,127]。 大家应该记住一些常见的补码的表示,这些数包括但不局限于下面表中列出的数:
 在这里插入图片描述
在这里插入图片描述

3浮点数存储

一般的编程语言都是将浮点类型的数据采用单精度类型( float)和双精度类型(double)来存储,float 数据占用 32bit,double 数据占用 64bit,我们在声明一个变量 float f= 2.25f; 的时候,是如何分配内存的呢?如果胡乱分配,那世界岂不是乱套了么,其实不论是 float 还是 double 在存储方式上都是遵从 IEEE 的规范的, float 遵从的是 IEEE R32.24 ,而 double 遵从的是 R64.53。无论是单精度还是双精度在存储中都分为三个部分:

  • 浮点数表示的数值:V = (-1)^s × M × 2^E
  • 符号(sign) :1个bit表示,当s=0,V为正数;当s=1,V为负数。
  • 阶码(exponent) :E的作用是对浮点数加权,用于存储科学计数法中的指数数据,并且采用移位存储。float类型的阶码是 8 bits,double类型的阶码是 11 bits。
  • 尾数(significand) :M是一个二进制小数,因为是二进制,所以科学计数法中这个值范围是:1≤M<2。(和十进制中范围为1~10一样)
    R32.24 和 R64.53 的存储方式都是用科学计数法来存储数据的。比如 8.25 用十进制的科学计数法表示就为:8.2510^1 ,而 120.5 可以表示为:1.205*10^2 ,这些小学的知识就不用多说了吧。而我们的傻蛋计算机根本不认识十进制的数据,他只认识 0, 1,所以在计算机存储中,首先要将上面的数更改为二进制的科学计数法表示, 8.25 用二进制表示可表示为 1000.01,

3.1 二进制十进制间小数怎么转换

十转二

  1. 十进制的小数转换为二进制,主要是小数部分乘以2,取整数部分依次从左往右放在小数点后,直至小数点后为0。例如十进制的0.125,要转换为二进制的小数。
    在这里插入图片描述

  2. 转换为二进制,将小数部分0.125乘以2,得0.25,然后取整数部分0
    在这里插入图片描述

  3. 再将小数部分0.25乘以2,得0.5,然后取整数部分0
    在这里插入图片描述

  4. 再将小数部分0.5乘以2,得1,然后取整数部分1
    在这里插入图片描述

  5. 则得到的二进制的结果就是0.001
    在这里插入图片描述
    二转十

  6. 二进制的小数转换为十进制主要是乘以2的负次方,从小数点后开始,依次乘以2的负一次方,2的负二次方,2的负三次方等。例如二进制数0.001转换为十进制。
    在这里插入图片描述

  7. 第一位为0,则0*1/2,即0乘以2负 一次方。
    在这里插入图片描述

  8. 第二位为0,则0*1/4,即0乘以2的负二次方。
    在这里插入图片描述

  9. 第三位为1,则1*1/8,即1乘以2的负三次方。
    在这里插入图片描述

  10. 各个位上乘完之后,相加,01/2+01/4+1*1/8得十进制的0.125
    在这里插入图片描述

因此 120.5 用二进制表示为:1110110.1 用二进制的科学计数法表示 1000.01 可以表示为 1.0001* 2^3,1110110.1可以表示为 1.1101101* 2^6。
在这里插入图片描述
IEEE 754对有效数字M和指数E,还有一些特别规定。前面说过,1≤M<2,也就是说,M可以写成1.xxxxxx的形式,其中xxxxxx表示小数部分。IEEE 754规定,在计算机内部保存 M时,默认这个数的第一位总是1,因此可以被舍去,只保存后面的xxxxxx部分。比如保存1.01的时候,只保存01,等到读取的时候,再把第一位的1加上去。这样做的目的,是节省1位有效数字。以32位float浮点数为例,留给M只有23位,将第一位的1舍去以后,等于可以保存24位有效数字。 道理就是在这里,那 24bit 能精确到小数点后几位呢,我们知道 9 的二进制表示为 1001,所以 4bit 能精确十进制中的 1 位小数点,== 24bit 就能使 float 能精确到小数点后 6 位。 ==

至于指数E,情况就比较复杂。 首先,E为一个无符号整数(unsigned int)这意味着,如果E为8位 (float类型) ,它的取值范围为0~255;如果E为11位(double类型),它的取值范围 为0~2047。但是,我们知道,科学计数法中的E是可以出现负数的(因为0.75用科学计数法表示就是1.1*2^-1),所以IEEE 754规定,存入内存时E的真实值必须再加上一个中间数,==对于8位的E,这个中间数是127;对于11位的E,这个中间数是1023。==比如,2^10的E是10,所以保存成32位浮点数时,必须保存成10+127=137,即10001001。

接下来我们看下 8.25用float类型存储的数据到底是什么样的?8.25f用二进制的科学计数法表示为:1.0001*2^3,按照上面的存储方式,符号位s = 0,表示为正;指数位 E = 3+127=130 ,尾数部分为1.0001,去掉最前面的整数1,就是M = 0001,所以8.25f用float类型在内存中存储的格式就是:
在这里插入图片描述
参考自:
https://www.cnblogs.com/mukekeheart/p/10517298.html
https://blog.csdn.net/u010867670/article/details/88869042
https://jingyan.baidu.com/article/425e69e6e93ca9be15fc1626.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值