二进制补码运算

2023-10-27

二进制负数的在计算机中采用补码的方式表示。很多人很好奇为什么使用补码,直接使用原码表示多好,看上去更加直观和易于计算。然而事实告诉我们,这种直观只是我们人类的一厢情愿罢了,在计算机看来,补码才是它们最想要的。那么,为什么计算机使用补码更好,又是如何通过补码来计算数值的呢?

我看过网络上很多解释补码的文章,几乎一致的回答就是符号位不变,其他各位逐位求反再加一。在此我想说,这些都不是根本原理。谁都知道这么求,数电第一章就明确写了怎么求,关键是为什么这么算,其中的原理是什么?

本文主要的内容就是深入讲解补码的原理,其中内容有相互引用成分及计算机基础要求,不适合初学者阅读。当然,随便看看无所谓啦。

1.什么是补码

    这个没有找到官方定义,只进行个人定义。   

    个人定义:补码是计算机中用来表示负数,使得负数能够使用加法器参与加法运算的一种码。

    加减是计算机中最常用的运算,加法一般使用加法器来实现,减法则使用减法器实现。那有什么办法可以将减法变为加法,这样就可以让系统只实现加法即可,答案就是补码。

    理解补码最简单的例子就是时钟。

    例1:

    假如一个时钟现在显示的是10点钟,如何将它调到6点钟?

    解:有两种方法,一是向后拨8个小时,二是向前拨4个小时

    在这个例子中,8 和 4 互为补数,也就是说4的补码是8,8的补码是4,而这个时钟的模就是12

    注意:可能有人会想,在往后调8个小时虽然也调到了6点,但是他实际上比原来日期多了12小时。是的,的确如此,但是你的时钟有地方存储了这多余的12个小时吗?答案是没有,所以在你调完后,你没有记录这12个小时,换句话说,你把这溢出的12个小时自动舍弃了。当第二个人来查看闹钟时间的时候,他看到的时间就是准的。

    例2:

    一个数的数值是11,他的模是16,那么他的补码是多少?

    解:16-11 = 5,即补码就是5。

2.模

   关于模没有找到固定的定义,简单来说模就是一个循环的周期,在例1中,时钟的一个周期就是12,所以模是12。一周的模是7天,一天的模是24小时。模是补码的一个重要概念。

3.使用补码运算

   例3

   模为32,使用补码运算该算式16-13,13 - 16。

   解 16-13 = (16 + (32-13))% 32 = 35 % 32 = 3 

    13-16 = (13 + (32-16))% 32 = 29 % 32 = 29

4.使用补码进行二进制运算    

    有看过数电基础的都应该记得,第一章就有说明二进制补码是如何运算的。正数的补码即为自己,负数的补码为符号位不变,其余逐位求反再加1。

    使用该定义,先通过例子求出数值,再对例子进行详细讲解,为什么可以使用负数的补码来运算。

    例4   通过二进制求15-11的值

    要想让减法变加法,必须转换算式为 15 + (-11)

    15为正数,符号位为0,二进制表示为 01111

     -11为负数,符号位为1,负数原码为  11011 ,补码符号位不变,其余逐位求反再 +1,即 10101

   所以 15 + (-11) = 01111 + 10101 = 100100 舍弃第一位溢出位,即00100,即+4

  这是一个最简单的补码算法运算的例子,却有很多不解之处。

 1.为什么负数 (-11 )逐位求反再+1就可以代表原来的数?

 2.为什么第一位舍弃

 3.为什么符号位能够参与运算

 先看问题1,-11 先不考虑符号,观察11的二进制表示,11使用二进制表示是 1011,将1011 逐位求反 得到 0100,因为是逐位求反,1011 +0100 = 1111 ,而1111 + 1 = 10000,发现了什么?10000是四位2二进制数的模。为什么10000是4位二进制数的模呢?原理也很简单,4位寄存器最高能表示什么数?即 (二进制)1111 = (十进制) 15 , 15 +1 =16 = (二进制)10000,后四位寄存器清0,所以模为16。

所以不管几位二进制数,取反后得到的值加原码会刚好的到所有的位都是1的二进制数,再加一就刚好进位得到模。所以取反加一是无论如何都能取到补码的。比如 :(原)101 +  (补)((反)010 +1) = 8 ,(原)10 + (补)((反)01 +1)= 4。

所以,负数符号位不变,其余逐位求反 +1 只是算出补码最简单的方法,而不是理论基础。

前面提到过,使用补码代替原码,计算后模掉溢出得到数值就可以得到计算的值了。

再看问题2,为什么高位舍弃,这个问题其实在例1中已经做了说明,因为你没有存储这个高位的空间,用最简单的解释来解释就是,一个4位的寄存器,只能存储数据的后四位,第一位进位没地方放,就像例1中多出来的12小时,没有地方存储,那么就丢弃了,反正结果正确就行。可能有人会问,你说丢弃就丢弃吗,丢了你怎么保证是正确的?

重新再看一次例4,现在考虑符号位,将符号位加入运算。

15 - 11 = 15 + (-11),其中 -11 为 11011(加了一位符号位,所以模为 16 * 2^1) 他的补码为 10101 = 21

所以 15 -11 变为 15 +21 = 36 (01111 + 10101) ,原先是减一个数,变换后却变成了一个比减数更大的加数了,能不溢出吗。所以要模掉溢出位 36 % 32 = 4 。仔细观察被模数36 = 1 00100 你会发现,在第二位之前的所有高位都是32的倍数,所以用32进行模运算就会全部清0,这就是为什么高位可以直接舍弃的原因,因为高位永远会是模的倍数,在模的过程中会被清0。

最后看问题3,为什么符号位能够参与运算,可能在这前面一直被符号位困扰,为什么参与运算就没有问题,看了这里的解释,我相信你讲不会再被困扰。

符号位对于我对二进制补码的理解产生了很大的阻碍,我不明白为什么符号位可以参与运算,而且算出来还是对的。花了不少时间理解了符号位的含义。

    首先放弃符号位就是计算机表示专门定义出来表示正数和负数用的这个思维,换成这样一种理解思路:我们观察计算机中一个二进制数,它没有专门的符号位,但是正数和负数在计算机中存储第一位二进制数会存在差异,如果它的第一位是0,那么他就是正数原码,如果它的第一位是1,那么他就是负数补码,我们通过观察第一位是0还是1即可知道这个数是正数还是负数。

通过以下例子,可以发现符号位其实是算出来的。

例5:计算机运算 9 - 12

 解:9 转五位二进制为 01001 //模为32(100000)

因为12是减数,所以将12转为补码变为加数,方便参与加法运算

12 = 01100(原) = 10011 + 1 = 10100(补)

01001 + 10100 = 11101

11101% 100000= 11101

从结果看,我们可以发现,第一位为1,第一位如果是1,那么这个数值是负数补码,由此可知,这个数是一个负数,只是在计算机中,他表示为11101,反求原码,即可得到 (11101 - 1) 反 = 00011  = 十进制数 3,由此可知,11101表示的是负数的3

从这个例子当中可以看到,在运算中完全没有考虑符号位,仅用单纯的加法运算进行运算,而得到的结果11101也没有人为去添加一个符号位,符号位是计算所得的,所以他才能参与运算。我们应该反过来看符号位,正是在补码运算中,存在第一位为0则是正数,为1则是负数这个规律,我们才方便地认定第一位为符号位,符号位跟人为定义没有任何关系(人为定义的符号位不可能满足数学规则参与数学运算)。

 

补充:在例5中可以发现,我们在第一位之前补了一个0,将四位二进制数补成五位二进制数来计算,为什么要补这个0呢?为了说明这个问题,我们来算一个错误的运算

例6:计算机运算 0 - 12

解 : 我们仅仅用四位二进制数(四位寄存器)来算

12 = (二进制)1100 12转为二进制后是一个四位二进制数,它的模为10000

因为12是减数,所以将12转为补码变为加数,方便参与加法运算

12 = 1100(原) = 0011 + 1 = 0100(补)

0000 + 0100 = 0100 = 4 ,第一位是0,说明是正数原码, 即运算结果为 +4

4 != -12 运算出错

通过结果发现,只用四位二进制数运算,结果是错误的,为什么会产生这种错误呢?因为寄存器位数不够,四位寄存器只能存储 0 -15 的数值,没有多余的寄存器位置用来表示这个数的正负,我们虽然算出了符号位,但是计算后所得到的符号位却没有地方存放,导致符号位缺失,我们又误将四位二进制数结果的第一位当做符号位来判断数的正负,才会出现错误的结果。

通过例5我们可以知道,符号位是计算后得出来的,所以我们要预先要在寄存器第一位留出一个位置存放计算后得出的符号位,所以我们先在第一位前面补一个0占位。

由此可知: 要想计算结果正确, 需要满足 : 寄存器位数 >= max(操作数1,操作数2,....) 的二进制位数加一位

 

最后,附上一张五位二进制数运算转换关系图,自己体会二进制数如何带着所谓的符号位在计算机中运算:

六位二进制运算转换关系图

有如下几点:

1:五位二进制数的所有正数都在圆环的黑线上,而负数都在圆环的红线上,如果在黑线上,那么六位寄存器第一位必为0,而在红线上,那么第一位必为1,我们也是通过这个位来判断数值的正负

2:五位二进制数运算结果取模后如果在黑线上,那么为正数,否则为负数

3:尝试写几个数字转为五位二进制数或者写几个算式对号入座,观察是否符合,加深理解

到这里补码的原理就差不多讲清楚了,无非是使用模进行转化,但是我们站在十进制的角度,去看二进制的东西,的确会显得相当费解。最后我想说,能发明补码来计算的数学家真的是太厉害了。

内容有相互嵌套成分,阅读后回顾前面的内容可能会更加深入理解。

还有很多特殊情况没有考虑,只讲解了最核心的内容。

本文纯属个人理解,如有纰漏,请勿拍砖。

 

 

转:https://blog.csdn.net/zhuozuozhi/article/details/80896838
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

二进制补码运算 的相关文章

  • 手把手教你搭建优雅的ssm框架(完整)

    直接开始搭建 使用的是idea工具 新建一个maven项目 加入框架支持 点开目录后 你会发现里面缺少目录 我们自己创建一下 在pom xml中添加依赖 这些依赖必不可少 后面可以根据需求自己添加
  • 第十四届蓝桥杯国赛python青少组题目

    LQGS14PB01 时间限制 3000MS 内存限制 589824KB 题目描述 编程实现 注 input 输入函数的括号中不允许添加任何信息 给定一个字符串S S长度 lt 100 统计字符串中字母一共有多少个 例如 S 1Abb 其中
  • keil 软件如何生成.hex文件

    1 当程序编译通过没错误了 按照下图步骤勾选 点击魔术棒 output界面 勾选hex 2 勾选完点击ok 再对程序进行编译 出现下图内容 则生成hex文件成功

随机推荐

  • C++ 学习笔记(二)

    C 继承与派生 1 公有继承 是指在源生一个类时继承方式为public的继承方式 在public继承方式下 基类成员在派生类中的访问权限为 基类的公有和保护成员的访问属性在派生类中不变而基类的私有成员不可访问 即基类的公有成员和保护成员被继
  • Vue中 element的table表格导入 与 导出为excel表格的实现

    Vue中 element的table表格导入 与 导出为excel表格的实现 一 导入 2 1 安装xlsx插件 2 2 新建导入功能组件 2 3 注册全局的导入excel组件 2 4 创建导入路由组件 2 5 封装导入接口 实现excel
  • QM二面

    目录 如何在笔记本上添加永久路由 扩展 Linux如何查看并杀死进程 模拟场景 动态路由协议和DNS的共同之处 如何在笔记本上添加永久路由 route print 查看路由表 添加路由的命令 route add 网段 mask 子网掩码 网
  • 从二叉树到堆排序

    目录 一 树 1 树的基本概念 2 二叉树 1 最常见表示二叉树的方法 2 满二叉树 3 完全二叉树 4 二叉树的性质 5 存储结构 二 堆 1 逻辑结构与存储结构 2 堆的特性 3 向下调整算法 4 建堆 5 堆排序 一 树 1 树的基本
  • 数据库模糊查询

    常用的模糊查询语句有 1 like 查询姓李的同学 使用like like 结合 代表多个字符 代表一个字符 SELECT id myname FROM aaa WHERE myname LIKE 李 like的用法就像我们使用百度搜索时啊
  • MQTT通讯之连接MQTT服务器

    根据 添加链接描述 和 添加链接描述 我的APP已经成功连接上MQTT服务器 至于怎么发布和接收 正在研究 研究好了 发上来 作者写的代码是Java的 但现在都推荐Kotlin 我就把转好的Kotlin代码发出来 package com e
  • Anaconda Python Pytorch (GPU) 配置

    目录 0 写在前面 1 Anaconda下载 1 1 下载 1 2 安装 1 2 1 设置安装路径 1 2 2 两个都勾上 1 3 查看conda版本 2 CUDA及cuDNN 2 1 查看是否可以安装CUDA 2 2 CUDA和Pytor
  • 【2022最新Java面试宝典】—— Java基础知识面试题(91道含答案)

    目录 一 Java概述 1 何为编程 2 什么是Java 3 jdk1 5之后的三大版本 4 Jdk和Jre和JVM的区别 5 什么是跨平台性 原理是什么 6 Java语言有哪些特点 7 什么是字节码 采用字节码的最大好处是什么 8 什么是
  • 什么是芯片?

    https zhuanlan zhihu com p 228757435 utm source weibo utm medium social utm oi 895441374156029952 utm content snapshot 什
  • k8s_day07_02

    k8s day07 02 静态密码方式认证k8s kubeconfig 1 kubeconfig 配置文件 在 etc kubernetes 有conf 结尾的文件 那个就是kubeconfig 类型的配置文件 用于控制节点组件 和api交
  • HBuilderX安装教程(非常详细)从零基础入门到精通,看完这一篇就够了

    一 下载安装 1 在地址栏中直接输入https www dcloud io 2 点击箭头所指 进去过后点击DOWNLOAD 3 点击过后 选择自己所需要的版本 HBuilder目前有两个版本 一个是windows版 一个是mac版 下载的时
  • python垃圾回收

    Python内存管理机制 Python内存管理机制主要包括以下三个方面 引用计数机制 垃圾回收机制 内存池机制 引用计数 举个例子说明引用是什么 a 1 如上为一个简单的赋值语句 1就是对象 a就是引用 引用a指向对象1 同理 b 1 b也
  • Configuring VM Acceleration on Windows

    http developer android com tools devices emulator html Configuring Virtual Machine Acceleration Caution As of SDK Tools
  • Java中String类,StringBuffer类和StringBuilder类

    底层分析 1 String类 String类对象代表不可变的字符序列 其底层结构如下 public final class String implements java io Serializable Comparable
  • quartz定时任务详解

    开始 application quartz xml
  • 前端面试题总结

    1 this指向问题 1 以函数的形式 包括普通函数 定时器函数 立即执行函数 调用时 this 的指向永远都是 window 比如fun 相当于window fun 2 以方法的形式调用时 this 指向调用方法的那个对象 3 以构造函数
  • NTP协议介绍

    查看原作者 转载自 NTP协议介绍 2013 06 19 14 50 50 转载 SNTP协议原理 SNTP是简单网络时间协议 Simple Network Time protocol 的简称 它是目前Internet网上实现时间同步的一种
  • 【分布式】分布式事务:2PC

    分布式事务的问题可以分为两部分 并发控制 concurrency control 原子提交 atomic commit 分布式事务问题的产生场景 一份数据被分片存在多台服务器上 那么每次事务处理都涉及到了多台机器 可序列化 并发控制 定义了
  • HttpServer:一款Windows平台下基于IOCP模型的高并发轻量级web服务器

    HttpServer的特点 1 完全采用IOCP模型 实现真正的异步IO 高并发 高可靠 2 支持4G以上文件下载 3 支持断点续传 4 轻量级 体积小 服务器文件仅200多K 无任何依赖库 5 支持CGI网关 通过CGI xml可动态配置
  • 二进制补码运算

    二进制负数的在计算机中采用补码的方式表示 很多人很好奇为什么使用补码 直接使用原码表示多好 看上去更加直观和易于计算 然而事实告诉我们 这种直观只是我们人类的一厢情愿罢了 在计算机看来 补码才是它们最想要的 那么 为什么计算机使用补码更好