原码、反码、补码

在学习C语言的过程中,有遇到补码这个问题,当时感觉懂了,有貌似不是很懂;然后查了一些文档,整理了一番,以后忘记了可以再翻开这篇文档,查漏补缺吧!

原码

原码是指一个二进制数左边加上符号位后所得到的码,且当二进制数大于0时,符号位为0;二进制数小于0时,符号位为1;二进制数等于0时,符号位可以为0或1(+0/-0)。上面是维基百科的解释,也就是说二进制的第一位只表示正负,正为0,负为1,8位表示的数值范围 [-127,127];

具体如下:

# +10的源码
0 0 0 0 1 0 1 0 # -10的源码
1 0 0 0 1 0 1 0

源码显而易见的优点是数值简单直观; 缺点是不能直接参与运算 ,例如+10 + (-10) = 0,换成二进制则变成了00001010 + 10001010 = 10010100 = -20显然是错的,所以原码的符号位不能直接参与运算,如果和其他位分开,这就增加了硬件的开销和复杂性;

反码

反码是一种在计算机中数的机器码表示。对于单个数值(二进制的0和1)而言,对其进行取反操作就是将0变为1,1变为0。

正数的反码等于其原码,而负数的反码则可以通过保留其符号位,将原码的数值位取反得到。

# +10的反码
0 0 0 0 1 0 1 0 # -10的反码
1 1 1 1 0 1 0 1

补码

正数和0的补码就是该数字本身。负数的补码则是将其对应正数按位取反再加1

为什么用补码?

  首先,要明确一点。计算机内部用什么方式表示负数,其实是无所谓的。只要能够保持一一对应的关系,就可以用任意方式表示负数。所以,既然可以任意选择,那么理应选择一种最方便的方式。

补码就是最方便的方式。它的便利体现在,所有的加法运算可以使用同一种电路完成。

还是以-8作为例子。假定有两种表示方法。一种是直觉表示法,即10001000;另一种是补码表示法,即11111000。请问哪一种表示法在加法运算中更方便?随便写一个计算式,16 + (-8) = ?

16的二进制表示是 00010000,所以用直觉表示法,加法就要写成:

  0 0 0 1 0 0 0 0
+ 1 0 0 0 1 0 0 0
-----------------
1 0 0 1 1 0 0 0

可以看到,如果按照正常的加法规则,就会得到10011000的结果,转成十进制就是-24。显然,这是错误的答案。也就是说,在这种情况下,正常的加法规则不适用于正数与负数的加法,因此必须制定两套运算规则,一套用于正数加正数,还有一套用于正数加负数。从电路上说,就是必须为加法运算做两种电路。

现在,再来看补码表示法

  0 0 0 1 0 0 0 0
+ 1 1 1 1 1 0 0 0
-----------------
1 0 0 0 0 1 0 0 0

可以看到,按照正常的加法规则,得到的结果是100001000。注意,这是一个9位的二进制数。我们已经假定这是一台8位机,因此最高的第9位是一个溢出位,会被自动舍去。所以,结果就变成了00001000,转成十进制正好是8,也就是16 + (-8) 的正确答案。这说明了,2的补码表示法可以将加法运算规则,扩展到整个整数集,从而用一套电路就可以实现全部整数的加法。

补码的本质

在回答2的补码为什么能正确实现加法运算之前,我们先看看它的本质,也就是那两个步骤的转换方法是怎么来的。要将正数转成对应的负数,其实只要用0减去这个数就可以了。比如,-8其实就是0-8。

已知8的二进制是00001000,-8就可以用下面的式子求出:

  0 0 0 0 0 0 0 0
- 0 0 0 0 1 0 0 0

因为00000000(被减数)小于0000100(减数),所以不够减。请回忆一下小学算术,如果被减数的某一位小于减数,我们怎么办?很简单,问上一位借1就可以了。所以,0000000也问上一位借了1,也就是说,被减数其实是100000000,算式也就改写成:

1 0 0 0 0 0 0 0 0
- 0 0 0 0 1 0 0 0
-----------------
1 1 1 1 1 0 0 0

进一步观察,可以发现100000000 = 11111111 + 1,所以上面的式子可以拆成两个:

  1 1 1 1 1 1 1 1
- 0 0 0 0 1 0 0 0
-----------------
1 1 1 1 0 1 1 1
+ 0 0 0 0 0 0 0 1
-----------------
1 1 1 1 1 0 0 0

所以负数的补码则是将其对应正数按位取反再加1是这样得出的

同理可以得出-128的补码为100000000 - 10000000 = 10000000,由此可知10000000表示-128的值,8位补码的取值范围[-128,127];

总结

补码系统的最大优点是可以在加法减法处理中,不需因为数字的正负而使用不同的计算方式。只要一种加法电路就可以处理各种有号数加法,而且减法可以用一个数加上另一个数的补码来表示,因此只要有加法电路及补码电路即可完成各种有号数加法及减法,在电路设计上相当方便。

另外,补码系统的0就只有一个表示方式,这点和反码系统不同(在反码系统中,0有二种表示方式),因此在判断数字是否为0时,只要比较一次即可。这就证明了,在正常的加法规则下,可以利用补码得到正数与负数相加的正确结果。换言之,计算机只要部署加法电路和补码电路,就可以完成所有整数的加法。一个字就是方便做运算;

【C语言】了解原码、反码、补码的更多相关文章

  1. 「C语言」原码反码补码与位运算

    尽管能查到各种文献,亲自归纳出自己的体系还是更能加深对该知识的理解.     本篇文章便是在结合百度百科有关原码.反码.补码和位运算的介绍并深度借鉴了张子秋和Liquor相关文章后整理而出.   目录 ...

  2. C语言原码反码补码与位运算.

      目录:     一.机器数和真值     二.原码,反码和补码的基础概念     三.为什么要使用原码,反码和补码     四.原码,补码,反码再深入     五.数据溢出测试     六.位运算 ...

  3. C语言学习笔记之原码反码补码

    原码:就是我们自己看的,以及机器输出给我们看的 补码:机器永远是以补码的形式将数据保存在计算机中 正数: 原码=反码=补码 负数: 反码:原码的符号位不变,其他位取反 ,1变0   0变1 补码:机器 ...

  4. JAVA:二进制(原码 反码 补码),位运算,移位运算,约瑟夫问题(5)

    一.二进制,位运算,移位运算 1.二进制 对于原码, 反码, 补码而言, 需要注意以下几点: (1).Java中没有无符号数, 换言之, Java中的数都是有符号的; (2).二进制的最高位是符号位, ...

  5. 原码 & 反码 & 补码 & 详解

    本篇文章讲解了计算机的原码, 反码和补码. 并且进行了深入探求了为何要使用反码和补码, 以及更进一步的论证了为何可以用反码, 补码的加法计算原码的减法. 论证部分如有不对的地方请各位牛人帮忙指正! 希 ...

  6. Java学习第五篇:二进制(原码 反码 补码),位运算,移位运算,约瑟夫问题

    一.二进制,位运算,移位运算 1.二进制 对于原码, 反码, 补码而言, 需要注意以下几点: (1).Java中没有无符号数, 换言之, Java中的数都是有符号的; (2).二进制的最高位是符号位, ...

  7. python之计算机硬件基本认知_数据单位_进制间转换_数的原码反码补码

    一:计算机硬件基本认知 cpu:   中央处理器.   相当于人的大脑.运算中心,控制中心. 内存:  临时存储数据. 优点:读取速度快,缺点:容量小,造价高,断电即消失. 硬盘:  长期存储数据. ...

  8. C 标识符, 数据存储形式(原码,反码,补码)

    一.  标识符 第一个字母必须是英文字母或下划线 二. 数据存储形式(补码存储) 最高位是符号位 ---- 0表示整数 ; 1 表示负数 1. 正数:原码 = 反码 = 补码 例子 : (10) 原码 ...

  9. java基础知识-原码,反码,补码

    1.正数:原码,反码,补码:都一样. 2.负数:和正数的储存方式不同,负数都是以补码形式存储的. <1>负数的补码 把负数的原码除了符号位取反后再+1. <2>负数的原码 把对 ...

  10. Java基础-原码反码补码

    Java基础-原码反码补码 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 注意,我们这里举列的原码和反码只是为了求负数的补码,在计算机中没有原码,反码的存在,只有补码. 一.原码 ...

随机推荐

  1. WinDbg常用命令系列---显示当前异常处理程序链!exchain

    !exchain 这个!exchain扩展命令显示当前异常处理程序链. !exchain [Options] 参数: Options下列值之一: /c  如果检测到异常,则显示与调试C++ try/c ...

  2. comlink 是来自google chrome 团队的简化webwokers 开发的类库

    comlink 可以帮助我们简单webworkers 的开发,同时很小(1.1kb),具体使用我们可以看下面 一张图  说明 comlink 使用起来也比较方便,官方也提供了完整的api 文档 参考资 ...

  3. prisma 已经支持mongodb了

    好久没有关注prisma 的版本迭代了,记得在去年12月份左右的时候,mongodb 在github 上还只是一个草案, 官方文档也没有相关的详细介绍,今天留意了下,居然已经支持了,还是很给力的(my ...

  4. windows客户端

  5. QBXT 2017GoKing problems 补完计划

    10.11 Updata : 烦死了...麻烦死了...不补了..就这些吧 20171001 上: 100 + 90 + 90 = 280 = rank 8 T1 /* T1 从最大的数开始倒着枚举 ...

  6. OpenFOAM——绕流振动

    流体的物性参数为: 密度:1kg/m3 粘度系数:0.01N·s/m2           首先进行建模操作,任何建模软件均可,本算例在ICEM建模和进行网格划分,生成的网格如下: 接下来转入Open ...

  7. 牛顿插值法(c++)【转载】

    摘自<c++和面向对象数值计算>,代码简洁明快,采用模板函数,通用性增强,牛顿差分合理利用存储空间,采用Horner算法(又称秦九韶算法)提高精度,减少时间复杂度,高!确实是高!对其中代码 ...

  8. 刷题之给定一个整数数组 nums 和一个目标值 taget,请你在该数组中找出和为目标值的那 两个 整数

    今天下午,看了一会github,想刷个题呢,就翻出来了刷点题提高自己的实际中的解决问题的能力,在面试的过程中,我们发现,其实很多时候,面试官 给我们的题,其实也是有一定的随机性的,所以我们要多刷更多的 ...

  9. spring boot +dubbo+zookeeper

    dubbo是一个分布式服务框架,致力于提供高性能和透明化的RPC远程服务调用方案,以及SOA服务治理方案. 结合本公司的开发也是用的dubbo这款优秀的框架,加上 最近工作重心的.所以对于dubbo的 ...

  10. 解决用官方容器启动redmine无法插入中文字符的问题

    jiangzhaowei@kitking:/kitking/redmineIot$ sudo docker-compose up -d Creating network "redmineio ...