计算机基础三: 二进制减法实现[通俗易懂]

计算机基础三: 二进制减法实现[通俗易懂]在上一章中了解了如何实现二进制加法,加法是始终从两个加数的最右列向左列进位计算的,而在减法中没有进位,只有借位.253-176=77上面的式子我们不难算出来,但习惯性的思维让我们用借位的方式求值.在不借位的情况下如何实现计算?借位是很麻烦的事情,虽然我们能够实现它,但这意味着额外的开销.我们将用一个小技巧,让我们避开借位从而实现减法.为了避免借位,我们先从百位最大值999中减去减数,而非从原来的被减数中减去减数.999-176=823这个方法称为对9求补

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE稳定放心使用

在上一章中了解了如何实现二进制加法, 加法是始终从两个加数的最右列向左列进位计算的, 而在减法中没有进位, 只有借位.

253 - 176 = 77

上面的式子我们不难算出来, 但习惯性的思维让我们用借位的方式求值. 在不借位的情况下如何实现计算?

借位是很麻烦的事情, 虽然我们能够实现它, 但这意味着额外的开销. 我们将用一个小技巧, 让我们避开借位从而实现减法.

为了避免借位, 我们先从百位最大值999中减去减数, 而非从原来的被减数中减去减数.

999 - 176 = 823

这个方法称为对9求补数. 176对9的补数是823; 反过来说823对9的补数是176. 这样一来, 不管减数是多少, 我们都不需要进行借位操作.

计算出对9的补数后, 将补数与原来的被减数相加:

253 + 823 = 1076

最后将结果加上1, 并减去1000

1076 + 1 - 1000 = 77

用代数思想代入一下, 就能知道为什么这样了, 这里就不再阐述. 我们再看另一个问题.

如果简述大于被减数, 也就是值为负数该怎么计算.

176 - 253 = -77

这与先前有些不同, 我们先用999减去253, 求出9的补数; 然后把9的补数和被减数相加

999 - 253 = 746
746 + 176 = 922

接着我们这里直接减去999, 但会出现借位, 并不符合需求. 将减数和被减数交换, 值取负数即可.

999 - 922 = -77

到此为止, 我们已经解决了十进制不借位做减法运算. 接下来让我们应用到二进制中.

(1111-1101) - (1011-0000) = ?

在十进制减法中, 我们需要用到9的补数, 同理, 二进制中我们需要用到1的补数. 而1的补数并不需要多复杂, 只需要将1取0, 0取1即可; 这也就是我们经常讲的反码.

1. 用8位二进制最大值1111-1111减去减数
(1111-1111) - (1011-0000) = 0100-1111
2. 将减数的反码与被减数相加
(1111-1101) + (0100-1111) = 1-0100-1100
3. 将上式所得结果加1
1-0100-1101
4. 减去1-0000-0000
(1-0100-1101) - (1-0000-0000) = 0100-1101

在这里我们先中断一下, 先了解二进制如何表示负数, 再来了解减数大于被减数的减法运算.

在十进制中, 我们使用+ \ – 号来表示数值的正负, 但二进制中我们不可能加符号, 因为仅有01两个数字.

当然我们可以取一位二进制位当做正负值, 但这带来的后果就是数值表示范围的缩小, 这不符合让它做更多的计算机思维. 在计算机科学中, 抽象的概念非常重要, 贯穿了整个计算机发展史, 现在让我们提升一层抽象.

在数轴上, 所有的数都是以0为中心, 对称无限延长. 但如果我们事先约定好大小, 那所有的整数都是已知的. 现在让我们将这个数轴头尾相连形成一个循环.
在这里插入图片描述
上图中内圈为实际数值, 而外圈则是表示数值. 我们可以看到最小的负数-10看起来像是10的衍生, 而最大的负数-1则表示为20.

在二进制中, 一字节所能表示的正整数为(0 ~ 255), 如果想要表示有符号整数, 则一字节取值范围为(-128 ~ 127). 最高有效位表示符号, 1为负0为正. 计算机又能充分利用8位所能表示的所有数值.

例如无符号整数125二进制表示位0111-1101, 为了表示-125, 我们需要先求125的补数1000-0010, 再加1, 得到1000-0011. 这就是有符号整数-125的二进制表示. 同样的步骤, 每位取反再加1, 就可以还原成无符号整型125.

利用这种机制我们将正负数自由的相加, 而不用用到减法. 但并不是完美, 这里我们约定的范围时一字节, 但两数相加超过一字节所能表示的范围时, 就会产生溢出. 也就是第九位数被舍弃了, 一般而言, 如果两个操作数的符号相同, 而结果与之不同, 这样的加法就发生了溢出, 属于无效.

现在单纯的一串二进制数值就有两种不同的使用方式了: 有符号, 无符号. 所以当你读取一段二进制时, 你得知道它有无符号才能知道对应的十进制数值; 同样的, 在编程的时候也应该使用关键字声明, 虽然很多编译器都自动认为省略就是无符号数, 但这是一个良好的习惯.

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/189943.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月5日 下午5:22
下一篇 2026年3月5日 下午6:01


相关推荐

  • Linux关闭防火墙命令(永久性关闭)

    Linux关闭防火墙命令(永久性关闭)抛开实际生产环境个人平时练习的时候安装虚拟机可能遇到过很多坑就很烦 可能很大一部分原因都是防火墙没关掉哈哈哈哈所以建议永久性关闭防火墙下面是 CentOs7 关闭防火墙的命令 1 查看防火状态 systemctlsta 如果是这样就开着呢如果是这样就是关着 2 暂时关闭防火墙 systemctlsto 重启防火墙 systemctlena 永久关闭后重启 Linux 永久关闭防火墙 firewalld 和 selli

    2026年3月18日
    2
  • 集合:映射,单射,满射,双射

    集合:映射,单射,满射,双射这些概念太重要了,虽然很不起眼,但是几乎所有地方都要用,一旦不清楚,会对一个问题审视错误。集合:元素汇聚在一起,就构成了一个集合。假设有集合A和集合B。映射:将A中的每一个元素,根据一个规则,对应到B中的一个元素去,比如A中是一些儿女,B中是他们的父亲,那么每一个A中的元素都可以对应到B中的唯一一个元素,这就是一种规则,即映射。因为一个人的爸爸只有一个,但是反之未必,因为一个爸爸可能有多个儿女。我们发现,这个和函数的概念非常相似,集合A相当于定义域,映射相当于f。但是集合的概念更加宽泛,正如前面所有

    2022年5月3日
    196
  • 手把手教你获取x信本地数据库(利用Sqlcipher查看)

    手把手教你获取x信本地数据库(利用Sqlcipher查看)最近一直在研究Xposed等一些hook框架,进行学习做一些demo,这次就正好拿x信练练手,学习学习,也可以学习x信手机本地数据库的表结构设计等。好,废话不多说,直接开干。前提是你的电脑已经安装了adb相关程序,如果你本身就是安卓开发者,想必肯定安装了AndroidStudio,那里直接就有adb相关程序。其次,你准备一台已经root过的安卓手机(要安装的有使用过的x信应用,不

    2025年8月22日
    3
  • ffi一些常见的错误

    ffi一些常见的错误1 安装失败现在 ffi 已经有两年多没人维护了 对于 Node 版本的快速迭代 ffi 现在已经连安装都可能失败了 本人测试的时候使用 node v10 x node gyp v3 8 的时候总会报错的 后面降级为 node v8 13 nbsp node gyp v3 7 安装的时候偶尔还是可以成功 建议着两个版本不要太新了 会造成 ffi 的一层底层报错 如果你降级了还是安装失败的话 可以考虑下一

    2026年3月17日
    2
  • linux扩容VBoxManage

    linux扩容VBoxManage//查看虚拟磁盘空间信息,确认确实是需要扩容的虚拟硬盘。VBoxManageshowhdinfo”F:\oracleVirtualBox\workspace\centos1\centos1.vdi”//计算要扩容的空间大小,我这里是要扩展到100G(1024*1024*1024*100)。set/a1024*1024*1024//扩展虚拟硬盘空间,最后的数字替换成上面计算出的硬盘空…

    2022年6月1日
    48
  • 跳转语句break和continue的区别「建议收藏」

    跳转语句break和continue的区别「建议收藏」在循环里面有两个关键操作break和continuebreak的操作是跳出当前循环continue是跳过本次循环注意:break可以用于for、switch、select,而continue只能用于for循环packagemain//必须有一个main包import“fmt”import“time”funcmain(){i:=0for{//for后面不写任何…

    2022年5月18日
    51

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号