首页betway必威体育app官网 › 从电脑为何用补码存储数据,衍生到存储单元数据溢出

从电脑为何用补码存储数据,衍生到存储单元数据溢出

引言

先说几句屁话,觉得啰嗦可以忽略跳过那段屁话。
俗话说:眼看他起高楼,眼看他宴宾客,眼看他楼塌了。我想那句话放在我们做技术的,也很有分寸——基础不牢,地动山摇。
即使大家有的是人不是做基础开发的,可是操作系统、数据结构和算法、总计机网络、设计方式……那个IT领域的基础性学科,对于大家的话其实挺主要的,比如做优化、跨语言学习、工程框架搭建……。基础即使不可能操纵眼前,但是可以控制我们在那条路上走多少路程。框架那么多、特效那么多,真心没有趣味一个个都摸四次,所以有时回过头去翻看那几个基础性的东西是挺有趣的。

  • 是不是还记得在学操作系统的时候,很可疑统计机为何要用补码存储数据,而不是用大家人更易于驾驭的原码来拓展仓储吗?

至于这么些难点,相信广大教那门课的教工以及工作连年的coder也表明不清,甚至不明了这一个概念。

  • 正文将尝试从理性结合感性的角度去印证微机为啥用补码存储数据,当大家明白那一个标题后,那么,大家就可以去领略另一个衍生难点——数量溢出。大家先来看一段有关数据溢出的Java代码片:

/*char是无符号数,16位存储,表示范围是0~2^16-1(即0~65535)*/
char ch = Character.MAX_VALUE; // ch为65535
ch += (char) 1; // 加1后,引起数据溢出,则ch为0

/*int是有符号数,32位存储,表示范围是-2^31~2^31-1(即-2147483648~2147483647)*/
int i = Integer.MAX_VALUE; // i为2147483647
i += 1; // 加1后,引起数据溢出,则i为-2147483648
  • 有关上述代码片的实施结果为何会如此,暂时不表达,希望因而小说循序渐进的进度来注脚溢出的题目。

fuck概念

  • 处理器用二进制来代表数据,那些大家应该都询问(不驾驭的找块板砖拍死自己算了)。
  • 没有更加表明,本文都以4位存储单元来阐明
  • 下边多少个小节会提到一些至关首要概念,不要对那个概念恐慌,那几个概念会结合例子依旧比较的款型,尽量以浅显简洁的文字来表达,保险人们都能看的懂

加法器

  • 处理器唯有加法器没有减法器,五个数的减法运算会被电脑转换为加法运算。(先埋个伏笔——通过补码举办表示,即可将减法运算转换为加法运算)

模、补数

  • 在平时生活中,有好多化减为加点例子。大家以最平凡的钟表为例,时针逆时针拨x(0<x<12)格和时针顺时针拨12-x格,效果是一致的。比如,时针从10点调整到5点有以下三种艺术:

    1. 时针逆时针拨5格,相当于做减法:10 -5 = 5
    2. 时针顺时针拨7(即12 - 5)格,相当于做加法:10 + 7 = 12 +5 =
      5(MOD=12)
  • 计算,x + (MOD - x) = MOD就是模,x和MOD -
    x就是一对“互补”的数,即原数x的补数为MOD - x或者原数MOD -
    x的补数为x。通过对钟表拨时针的例子可以发现,用补数(7)代替原数(5),可把减法转变为加法(现身的进位就是模,进位遗弃)。

二进制数的模,先来看下四个个例子(此处大家忽略符号):

  1. 2位存储所能表示的最大数是11(10进制:3 = 2^2 -
    1),比她大1的是11 + 1 = 100(10进制:4 =
    2^2),那么那些100则是2位存储所能表示的拥有数据的模。
  2. 4位存储所能表示的最大数是1111(10进制:15 = 2^4 -
    1),比她大1的数是1111 + 1 = 10000(10进制:16 =
    2^4),那么那么些10000则是4位存储所能表示的有着数据的模。

因而对上面多个例子可以推测:一个二进制数的万丈位位数用n表示,那么该二进制数的模就是2^n

原码、反码、补码

  • 先来看一张国内外教材相比较的表(出自《计算机教育》二零一五年第10期的稿子——《原码、反码和补码的教学钻探》)

国内外教材相比较.png

在意下ones' complement和 two's
complement的撇号(')的义务(学过德语的都知情,撇号(')在s前和s后的意思是不等同的)

  • 给定一个有标志数x,来相比较下国外和国内教材对原码、反码、补码的表示:

    • 域外教材
      • sign and magnitude
        representation(原码):最高位位符号位(0代表正数,1代表负数),剩余位(数据位)为x的大大小小。
      • ones' complement
        representation(反码):如若x为正数,则是其二进制表示;假如x为负数,则是其相应正数的bit
        complement/bitwise
        NOT(按位取反)——执行每一位逻辑否定的一元操作。可用公式表示为:

        • [x]反 = (2^n - 1) -
          |X|(其中n为将符号位算在内的位数,|X|为相对值)
      • two's complement
        representation(补码):若是x为正数,则是其二进制表示;如若x为负数,则是其对应正数的二的补(所有位取反后加1)。可用公式表示为:

        • [x]补 = (2^n) - |X| = [x]反 +
          1(其中n为将标志位算在内的位数,|X|为相对值)
    • 境内教材
      • 原码:最高位为标志位,剩余位(数据位)为x的相对值。
      • 反码:若是x为正数,则与原码相同;倘诺x为负数,符号位保持不变,数据位取反。
      • 补码:如若x为正数,则与原码相同;要是x为负数,符号位保持不变,数据位取反,然后加1(若符号位有进位,则抛弃进位)。
  • 比较国内外教材的抒发,是还是不是察觉高下立现:

    • 国内教材画蛇添足,并且不难招惹误解:
      1. 原码是反码和补码的基础,反码和补码由原码转化而来
      2. 原码、反码和补码的符号位相同
    • 域外教材,则尤其浅显:
      1. 求解一个数的反码和补码,根本不须要精晓原码,直接通过它们的三个对应公式即可,甚至可以说原码与反码和补码没有半毛钱关系,反倒是反码和补码存在关联——补码
        = 反码 + 1
      2. 原码的出发点是标志的表示(符号位),即用0表示正数,用1意味着负数;反码和补码的着眼点是减法的演算,即用七个正数的加法取代三个数的减法

狗日的国内教材和翻译,真是误人子弟啊

总结机为何用补码存储数据

  • 上边铺垫了那门久,终于要进来第四个主旨——计算机为啥用补码存储数据。为了不引起混淆,大家就以海外教材对于原码、反码和补码的表示法来展开验证。简单起见,以4位存储表示有号子数为例,通过原码、反码和补码的表示法来生成一张表:

|有号子数(十进制)|sign and magnitude representation(原码)|ones'
complement representation(反码),[x]反 = (2^n - 1) - \X|two's
complement representation(补码),[x]补 = (2^n) - \X|
|:-:|:-:|:-:|:-:|
|+7|0111|表示方法不变|表示方法不变|
|+6|0110|表示方法不变|表示方法不变|
|+5|0101|表示方法不变|表示方法不变|
|+4|0100|表示方法不变|表示方法不变|
|+3|0011|表示方法不变|表示方法不变|
|+2|0010|表示方法不变|表示方法不变|
|+1|0001|表示方法不变|表示方法不变|
|+0|0000|表示方法不变|表示方法不变|
|-0|1000|1111|0000(求解过程:[x]补 = 2^n - \x\ = 2^4 - \-0\ = 2^4

  • (+0),使用二进制则为10000 - 0000 =
    10000,超过4位(有进位),那么放弃进位1,最后结出就是0000)|
    |-1|1001|1110|1111|
    |-2|1010|1101|1110|
    |-3|1011|1100|1101|
    |-4|1100|1011|1100|
    |-5|1101|1010|1011|
    |-6|1110|1001|1010|
    |-7|1111|1000|1001|
    |-8|超出4个bit所能表明范围|超出4个bit所能表明范围|1000|
    |备注|零重码,二进制存在二种象征方法:0000和1000|零重码,二进制存在二种表示方法:0000和1111|零无重码,同时缓解了原码和反码不可以表示-8的题材|

  • 透过上述表格,可以很自然的下结论出一个结论:补码表示法(two's
    complement
    representation)能够防止0的机器数重码,同时又解决了原码和反码无法代表-8的题材
    ,那样就大幅度的简化了统计机的硬件设计。

  • 组合之前涉嫌的钟表例子,大家把补码表示法(two's complement
    representation)所表示的四位存储单元,根据从0000到1111递增的艺术,均匀的遍布在时钟的表盘上。于是,咱们就能够取得下边那张图(图片来源于于这里):

two's complement wheel

  • OK,继续以时钟的办法来观察上图:

    • 顺时针方向位加法,逆时针方向为减法
    • 模为2^n:在1111处顺时针拨一格,就到了0000。用数学的艺术,即1111 +
      1 =
      10000,进位甩掉则结果为0000,那么四位存储的模就是10000(2^4)
    • 减法转换为加法:3 - 1 = 3 + (-1) = 0011 + 1111 =
      0010,眼尖的人可能会说0011 +
      1111可想而知极度10010,怎么会是0010?还记得此前提过的最高位进位放弃嘛,因而对于4位存储来说,进位放弃后就是0010
      = 2。

      若减法不变换为加法,那么3 -1 = 0011 - 0001 = 0010 = 2

    • 数量溢出:当0111(7)加1时,依照大家人的思考来说,应该结果为8,然则对于机器来说则不是,因为0111(7)是四位存储所能表示的最大有标志数,所以它是力不从心表示01000(8)的,那个时候我们就说多少溢出了。那么数量溢出该怎么办吧?很不难,机器的合计格局明确和大家人脑不等同,机器按照地点环形图的格局,由于0111(7)加1是顺时针造成的数码溢出,那么我们得以把机器的操作想象成在0111(7)处顺时针拨了一格,我们再去对待下环形图发现此时指向了1000(-8)。

      把那个历程想象成拨时针就OK了,对于1000(-8)减1也是一样道理

  • 从那之后,大家完全可以总括一下,并解答总结机为啥用补码存储数据:

    1. 微机唯有加法器没有减法器,多个数的减法运算会被电脑转换为加法运算,而补码正好能够解决减法转换为加法的标题
    2. 提防机器发出零重码,同时缓解了原码和反码不可以表示-8的题材,那样庞大的简化了电脑的硬件设计
    3. 以巡回的法门解决多少溢出的题目

从补码的角度解答代码片中的数据溢出

  • 既然已经明白了电脑为啥用补码存储数据,那我们就足以回过头去扑灭小说初叶的数额溢出的代码片了。由于代码片中ch和i的标题是平等的,那大家就分选ch来实行分析,另一个雁过拔毛你们分析。

  • 在Java中,char为无符号数,16位存储,表示范围是0~2^16-1(即0~65535)。

    1. 首先,大家按照0000 0000 0000 0000到1111 1111 1111
      1111递增的主意,均匀的分布在时钟的表面上,图就不画了,自己在脑中想象一下要么画个草稿。
    2. 然后,找出多少溢出点,通过阅览char环形图可以窥见数目溢出点是0(0000
      0000 0000 0000)和65535(1111 1111 1111 1111)
    3. 终极,大家的ch = 65535 +
      1,那么很明朗发生了数额溢出,根据拨时针的法门就足以汲取ch = 0
  • Perfect,是不是解答了当初学操作系统和编程的时候,烦扰你们很久的题材。送给我们一句话:有些概念可能马上不知晓,可是随着阅历多积累和回忆的多了,任其自流就知道了。

贴出我看的有关补码的篇章链接,有几篇普通话小说对于一些知识点可能说错了,切记要带着批判的看法去看:

转载本站文章请注明出处:bway883.com https://www.piworx.com/?p=5058

上一篇:

下一篇:

相关文章

网站地图xml地图