关于计算机是如何存储数字(源码,反码,补码)

文章分为两部分:一个是整数,一个是小数

先说整数

假设我们有1个字节来存储数字

一个字节 = 8个比特位,按理来说能表示的数字范围为:0(00000000)~ 256(11111111)

但是如果有负数的话怎么处理?

方法是:将最高位表示成符号位,其中0代表正数,1代表负数。

即:1 = 00000001,-1 = 10000001

仅仅这样的话,运算(比如1+ -1)对机器就变得非常不方便。为了运算方便,我们引入了原码,反码,补码的概念。

原码:最初的二进制位,其中最高位为符号位

反码

  • 如果是正数,原码 = 反码;
  • 如果是负数, 将0变为1,1变为0,符号位固定(这里的符号固定意味不能将符号位的1变为0

补码

  • 如果是正数,原码 = 反码 = 补码 ;
  • 如果是负数, 对反码进行加 1 操作,符号位固定(这里的符号位固定意味着从反码变为补码时,符号位不参与进位操作,从补码变为反码时不参与借位操作

这样的话 1 和 -1 就如下表:

数字 1 -1
原码 00000001 10000001
反码 00000001 11111110
补码(计算机实际存储的格式) 00000001 11111111

此时 1+(-1) = 00000000 (二进制)= 0(十进制)

加法运算时,符号位是参与运算的

[Tip]
写到这里我们来解释一下为什么两数相减( 或者说正数和负数相加),最后的结果等于两数字补码相加的结果。
比如有个钟表,现在指向的是10点,我们想让他指向5点。有两个办法,一个是顺时针拨动7点,一个是逆时针拨动5点,即:

  • 10 + 7 = 17 -12 = 5
  • 10 - 5 = 5

在这个例子中,-5 的补码就是 7,所以减法运算的公式就为:

  • X - Y = X + (- Y)的补码

当按照补码格式来存储数字时,一个字节的存储范围就是:

补码 十进制
00000000 0
00000001 1
00000010 2
…… ……
01111111 127(因为最高位为符号位,所以127就是一个字节能存储的正数的上限)
10000000 -0(对01111111进行+1操作变为10000000,但是因为是补码,所以10000000 = 0)
10000001 -127
10000010 -126
…… ……
11111110 -2
11111111 -1

补码的分布看起来像个圆

上面说到,对于一个字节来说:

  • 如果是无符号的话能表示的数字范围为 0(00000000)~ 256(11111111)
  • 当有了符号,能表示的数字范围就为:-127(11111111)~ 127(01111111)
  • 但是实际上对于一个字节来说能表示的数字范围其实是 -128 ~ 127,127能理解,-128是为什么?
  • 按照上面的表格来说,范围依然是 -127 ~ 127 ,怎么来的 -128 呢?其实是因为在补码中由于 00000000 表示的是0 ,10000000 表示的也是 0 ,所以就人为规定 10000000(补码) = -128
  • 正是由于计算机是按补码存储的,所以范围才是 -128 ~ 127。

但是要注意 -128 是没有对应的反码和原码的(在一个字节里)。

我们总结一下,在一个字节中:

  • 反码和原码的表示范围是:-127 ~ 127,
  • 补码: -128 ~ 127,
  • 由于计算机是按补码存储的,所以范围是: -128 ~ 127

这就是整数在电脑中的存储,那么小数是在电脑中如何存储的呢?

小数存储

在C中我们一般用到小数,选择的数据类型是 float 或者 double,所以我们就以 float 来举例说明。

已知 float 在64位机器占4个字节 = 32个比特位.

假设有一个小数 = 5.5,我们要把它存储进32个比特位里面,但首先我们要确定下面几点:

  • 5.5(十进制) = 101 . 1(二进制)
  • 注意不是 101.101,因为 0.5 是 1 乘以 (2 ^ -1)
  • 即:101.1 是 1 * (2^2) + 0 * (2^1) + 1 * (2^0) + 1 * (2^-1)
  • 所以 101.1 等于 101.1 * (2^0) ,表示成科学计数法为 1.011 * (2^2)

将 5.5 = 1.011 * 2^2 存储进32个比特位:

位数 内容
[1]第一位 存的是正负号(这里是0)
[8]接下来八位 存的是指数上的数据(这里是2)
[23]23个比特位 存的是小数点后面的数字,(这里是0110000000000000……)

而对于 double 类型来说:

位数 内容
[1]第一位 存的是正负号
[11]接下来十一位 存的是指数上的数据
[52]52个比特位 存的是小数点后面的数字
全部评论

相关推荐

最近群里有很多同学找我看简历,问问题,主要就是集中在明年三月份的暑期,我暑期还能进大厂嘛?我接下来该怎么做?对于我来说,我对于双非找实习的一个暴论就是title永远大于业务,你在大厂随随便便做点慢SQL治理加个索引,可能就能影响几千人,在小厂你从零到一搭建的系统可能只有几十个人在使用,量级是不一样的。对双非来说,最难的就是约面,怎么才能被大厂约面试?首先这需要一点运气,另外你也需要好的实习带给你的背书。有很多双非的同学在一些外包小厂待了四五个月,这样的产出有什么用呢?工厂的可视化大屏业务很广泛?产出无疑是重要的,但是得当你的实习公司到了一定的档次之后,比如你想走后端,那么中厂后端和大厂测开的选择,你可以选择中厂后端(注意,这里的中厂也得是一些人都知道的,比如哈啰,得物,b站之类,不是说人数超过500就叫中厂),只有这个时候你再去好好关注你的产出,要不就无脑大厂就完了。很多双非同学的误区就在这里,找到一份实习之后,就认为自己达到了阶段性的任务,根本不再投递简历,也不再提升自己,玩了几个月之后,美其名曰沉淀产出,真正的好产出能有多少呢?而实际上双非同学的第一份实习大部分都是工厂外包和政府外包!根本无产出可写😡😡😡!到了最后才发现晚了,所以对双非同学来说,不要放过任何一个从小到中,从中到大的机会,你得先有好的平台与title之后再考虑你的产出!因为那样你才将将能过了HR初筛!我认识一个双非同学,从浪潮到海康,每一段都呆不久,因为他在不断的投递和提升自己,最后去了美团,这才是双非应该做的,而我相信大部分的双非同学,在找到浪潮的那一刻就再也不会看八股,写算法,也不会打开ssob了,这才是你跟别人的差距。
迷茫的大四🐶:我也这样认为,title永远第一,只有名气大,才有人愿意了解你的简历
双非本科求职如何逆袭
点赞 评论 收藏
分享
很奥的前端仔:如果你接了offer 临时又说不去 hr确实要多做一些工作。 当然如果是接offer之前当我没说
点赞 评论 收藏
分享
评论
1
1
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务