原码:最左侧一位表示符号,且0表示正数,1表示负数;二进制转换为十进制时,符号位只用于取正负号,不参与转化。

例如1个字节的二进制:
0000 0001表示十进制的1;
0000 1010表示十进制的10;
1000 0001表示十进制的-1;
1000 1010表示十进制的-10;
根据原码的定义规则可知对于1个字节的有符号二进制原码的取值范围:[11111111]~[01111111]。即[-127]~[127]。比较特殊的是[10000000]表示-0,[00000000]表示+0,但是+0和-0是没有意义的,后面讲到补码时会说到如何解决+0和-0的问题。这样,对于1个字节的有符号二进制就可以表示256(2的8次方)个数值,包括+0和-0。
由以上可以看出,原码表示法简单直观,但是对于计算机来说,要使计算机能够自动识别最左侧的符号位,就需要更为复杂的硬件设计;
另外,在原码做减法运算时,根据数学上的加减乘除规则无法算出正确的值:
例如:1-1=1+(-1)=[00000001]原+[10000001]原=[10000010]原=-2
发现1-1不等于0。
总之,用原码作为计算机的存储方式不合适。

由上面可知,计算机不适合存储原码的原因是:1,无法识别二进制左侧的符号位;2,做减法时无法获取正确的结果。那么,有没有一种方式可以既不用考虑二进制左侧的符号位,又能够不做减法呢?

先来看一个时钟的例子,不考虑分和秒,生活中的钟表共1-12这12个刻度,假如此时时针指向6点钟方向,要想让它指向2点钟方向则有两种方式:1,逆时针移动4个刻度记作-4;2,顺时针移动8个刻度记作+8。可发现,-4的绝对值加8等于12。则我们称-4和8对于mod12互为补数。同样-3和9对于mod12互为补数。也就是说我们可以找到一个正数(8)代替负数(-4)用加法代替减法,且结果不变,如下图。

模拟时钟的逻辑,对于1个字节的二进制,共有256(2的8次方)种排列方式也就是可以表示256个数(类似于时钟的12个数),则其mod为256。

补码:正数的补码是其本身;负数的补码是符号位不变,其余各位取反后再加1,也就是反码加1。
例如:十进制数1的原码是0000 0001,其补码也是0000 0001,不把左侧第一位当成符号位直接转换成十进制仍是1。
 十进制数10的原码是0000 1010,其补码也是0000 1010,不把左侧第一位当成符号位直接转换成十进制仍是10。
 十进制-1的原码是1000 0001,则其补码是1111 1111,不把左侧第一位当成符号位直接转换成十进制是255,发现|-1|+255=256,说明-1的补码就是其补数。
 十进制-10的原码是1000 1010,则其补码是1111 0110,不把左侧第一位当成符号位直接转换成十进制是246,发现|-10|+246=256,说明-10的补码就是其补数。

通过上面的例子,你会发现:1,补码不用考虑符号位;2,补码用加法代替了减法。这就很好的解决了原码的两个缺点。

为什么负数的补码是符号位不变,其余各位取反再加1呢?
看看下面-10转换为补码的流程:
   1 0 0 0 1 0 1 0   -10
   1 1 1 1 0 1 0 1   取反
+                        1   加1
由上可知,取反后原来是0的位变成了1,则弥补了原来的位权(eg:对于1000,1的位权是1*2的3次方,左侧第一个0的位权是0*2的2次方)为0的问题;原来是1的位变成了0其位权也变为0;符号位也不再表示符号位而是1*2的7次方,因此取反会转换为十进制为245,再加1变为246,246+|-10|=256。因此负数的补码是符号位不变,其余各位取反再加1。

有了以上的了解,对于1个字节的内存空间我们可以把数据在其中存储的情况想象成一个钟表的表盘:

对于上面的图片:
1:1个字节的内存空间其0和1的组合方式有256(2的8次方)种。
2:内圈的数值(无符号)是计算机中实际存储的补码对应的十进制。即不把符号位当成符号位而是当成普通的二进制位后的十进制数。其取值范围是0~255,共256个数,可以理解成    钟表的256个刻度,即mod为256,内圈(补码)的运算无符号无减法。
3:外圈的数值(有符号)是考虑符号位后补码对应的原码的十进制值,也是我们实际需要的值。其取值范围是-128~127,共256个数(很多人不理解为什么范围不是-127~127后面会解    释)。
4:已经知道原码的取值范围是[-127]~[127],包括+0(00000000)和-0(10000000);
   因为1-1=1+(-1)=[0000 0001]原+[1000 0001]原=[0000 0001]补+[1111 1111]补=[1 0000 0000]补=[0000 0000]补=[0000 0000]原=+0,其中[1 0000 0000]补中的最高位1因为      溢出而被自动舍弃成[0000 0000]补。所以对于1个字节的内存我们可以用[0000 0000]补表示0(+0)。
  
  又因为-128=-1-127=(-1)+(-127)=[1000 0001]原+[1111 1111]原=[1111 1111]补+[1000 0001]补=[1 1000 0000]补=[1000 0000]补,其中[1 1000 0000]补的最高1溢出而自动舍     弃成[1000 0000]补,因此对于1个字节的内存可以用[1000 0000]补来表示-128,需要说明的是[1000 0000]补只是拿出了原码中的-0的二进制形式用来表示-128的补码形式,因   此并没有原码和反码,视图通过[1000 0000]补获取其原码或反码的做法是错误的。
  所以外圈取值范围是-128~127,而不是-127~127。
5:计算机中存储的是内圈的值(无符号无减法),而表现出来的却是对应的外圈的值,即,计算机中存储的是数的补码,每一个补码对应一个原码。
总结:采用补码存储的方式,计算机不需要考虑符号,也不需要做减法。

下面举1个例子验证一下上图是不是正确:
eg1:验证-127逆时针移动2为指向127。
因为-127的补数是129(10000001),-2的补数是254(11111110)

所以-127-2=(-127)+(-2)=[1111 1111]原+[1000 0010]原=[1000 0001]补+[1111 1110]补=[1 0111 1111]补=[0111 1111]补=[0111 1111]原=127。

另外:根据数据在内存中是以补码的形式存放的原理,可以很好理解,低字节向高字节扩展时,是带符号扩展的。

例如:两个字节的有符号数,扩展为4个字节时,若为负,则左侧所有字节全补1;若为正,则左侧所有字节全补0.

两个字节的无符号数扩展为4个字节时,则左侧全补0.

原码、补数、补码以及计算机中为什么用补码存储相关推荐

  1. 原码、反码、补码,计算机中所有的数都是以补码的形式存储的

    计算机中所有的数都是以补码的形式存储的 原码: 一个数的原码就是其10进制的数转换为2进制数,正数的原码符号位为0,负数的原码符号位为1. 如10进制的数26667,将其转换为2进制为0110 100 ...

  2. 原码和补码在计算机中的应用,原码,补码和反码在计算机中的作用

    满意答案 xxyy5566123 2013.06.26 采纳率:58%    等级:12 已帮助:13466人 引入原码 反码 和补码的目的就是为了解决减法问题,因为计算机CPU的运算器中只有加法器, ...

  3. 原码、反码、补码,计算机中负数的表示

    原码:将一个整数,转换成二进制,就是其原码.如单字节的5的原码为:0000 0101:-5的原码为1000 0101.反码:正数的反码就是其原码:负数的反码是将原码中,除符号位以外,每一位取反.如单字 ...

  4. 计算机数字表示方法有哪些,补码(计算机中数字的表示方式)

    在计算机中,使用二进制表达数字,例如,一个字节(8位)可表示的范围是0到255(在不考虑符号的情况下),即00000000到11111111. 考虑到数字有正负,我们第一时间想到,空出一位来表示符号位 ...

  5. 为什么计算机中负数用补码表示

    可以直接从第三部分(计算机中数的存储和运算)开始看. 文章目录 0x00 机器数和真值 0x01 原码.反码和补码 0x02 计算机中数的存储和运算 0x03 实例运算 实例一: 实例二: 0x00 ...

  6. 计算机补码的表示形式,补码(计算机中数字的表示方式)

    在计算机中,使用二进制表达数字,例如,一个字节(8位)可表示的范围是0到255(在不考虑符号的情况下),即00000000到11111111. 考虑到数字有正负,我们第一时间想到,空出一位来表示符号位 ...

  7. 原码除法运算(计算机组成原理19)

    原码除法运算 视频链接地址: https://www.bilibili.com/video/BV1BE411D7ii?from=search&seid=6420326887479343502 ...

  8. 负数在计算机中的表示和存储

    (整理+学习) 在计算机系统中,数值一律用补码表示和存储.含符号位和数值位,符号位:0表示"正": 1表示"负". 正数的补码 = 原码 负数的补码 = 负数的 ...

  9. C语言 65535的补码,65535(计算机中65535表示什么)

    65536是2的16次方.无符号整型变量int大小是4字节也就是16bit(位),故可以表. (十进制0)表示到1111111111111111B(十进制65535).如有任何问题,欢迎追问. 就是在 ...

最新文章

  1. java文件锁定_如何使用java锁定文件(如果可能的话)
  2. 博客迁移至http://www.vlix.org/
  3. 提高sqlmap爆破效率
  4. 反模式? 只有模式不彻底吧
  5. 学习进度条(第六周)
  6. HornetQ之JMS2.0 (实例讲解)
  7. Linux内核链表访问链表头指针,linux内核——链表结构分析
  8. Android的JNI【实战教程】6⃣️--温控计
  9. 西门子S7系列中间人攻击:PLC探测和流量分析(二)
  10. Altium Designer 18生成Gerber教程
  11. html菜鸟教程zoom,插件 jQuery.panzoom 中文API文档
  12. CronTrigger表达式
  13. 50条最隐讳的笑话,只有最聪明的人才能理解
  14. NOIp 2020 微信步数 题解
  15. 奉劝想把编程学好的学弟们 · 如何高效学习编程?
  16. 开关电源串模扼流圈、共模扼流圈选择方法
  17. 爬取动态网站表格内容
  18. 王家林最受欢迎的一站式云计算大数据和移动互联网解决方案课程 V1之Android架构设计和实现完整训练:HALFrameworkNative ServiceAndroid ServiceBes
  19. 三自由度求解正逆运动学
  20. python图片批量裁剪

热门文章

  1. ErrMsg:server is DOWN now, please try again later!
  2. 综测仪 IQ简介和IQview使用方法
  3. 花前挥手别伊人,月下纵马扬轻尘,红尘游历,荡剑江湖。四方辗转,看千山飞鸟逐;万里飘蓬,叹海角天涯路。夜风萧瑟雨凄楚,相思情入梦,孤影独对窗前烛,离别意难书。何时平尽心中愿,从此相守不离疏,岁岁年年情深
  4. Input的常用属性
  5. C++ 获取本机所有的网卡配置、IP地址和Mac地址
  6. openGL应用复杂度评价
  7. 推荐几个Python爬虫接单渠道
  8. Google GWT
  9. win11账户锁定了怎么解除?
  10. Sqlserver官网下载时各版本含义