关于二进制补码的若干注记

2023-11-03 13:38
文章标签 二进制 若干 补码 注记

本文主要是介绍关于二进制补码的若干注记,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

二进制补码是在《计算机科学概论》中讲授的基本概念,本注记试图讲述:什么是补码,为什么需要补码,补码的运算规则,而最重要的是试图说明,补码规则为什么是如此定义的。从而引申出一个也许不大准确的结论:计算机科学理论是源于实践又反作用与实践的理论,至少从理论上看是如此。

为什么需要补码

定义补码是为了满足计算机表示负整数(也称带符号整数)的需要。有基本知识的都知道,计算机是用二进制来表示数字,即只用0/1两个数字表示数字,如果要表示负数应该怎么办呢?

补码的规则

补码的规则是非常简单的,要表示某正数的负数,只需要对该二进制数取反然后加1 。比如,0011表示十进制的正整数3,那么-3的补码表示就是 1100+1=1101 。(为方便起见,所有例子都使用4比特二进制数来表示。)

基本上,大部分的同学学到这里也就停止了,规则定下来,我们遵守就是了。只有少数同学或者老师会继续提问,为什么补码的定义是取反加1(而不是其他规则),为什么要这样定义,这样定义的依据是什么?以下我试图解释这个问题。

为了证实表示负数用补码的定义是正确的选择,我们可以从反面出发,看看几种不正确的但显然是非常直观的定义。

直接在正整数之前加符号

这种想法最最直观直接了。大家看,要表示带符号数,我们必然需要使用一个比特来代表所谓的符号,就选0代表整数,1代表负数,因此,如果表示-3,那只需在+3前面加负号即可,也就是说3是0011,那么-3就是1011 。这样不就很好了吗?

首先注意,4比特二进制在无符号的时候,表示的范围是0~15,即0000~1111 。在表示带符号整数时,因为抽出了一为作为符号位,那么表达的范围就应该是:

0000~0111 (0~7) 以及 1000~1111 (-0~-7)

一个立即需要解决的问题就是0与-0从含义(定义)上怎么区别?而更为重要的是,符号的出现还直接影响了算术运算规则的定义。比如,原本我们很容易定义加法来做正整数运算,比如0011+0001= 0100(3+1=4),但是这个加法对带符号数就立即失效了,比如0011+1001=1100=(3-1=-4)。

小结一下,在定义带符号数的时候我们有两个问题需要解决:0与-0该如何区分、定义或者解决,其次,使得无符号的加法在带符号的加法保持相容。

对正整数取反

这种想法也非常直观。负数与正数不是刚刚相反吗,那么给定一个正二进制数,只需把每一位都取反不就刚好对应一个负数么?比如,0011(3)的反就是1100(-3)。此时,四比特的带符号二进制数的范围就是:0000~0111 (0~7,与上一个例子相同) 以及 1000~1111 (-7~-0,注意,与上一个例子相比,顺序是颠倒了的。) 。

我们需要问,刚才的问题解决了没有?稍微分析一下,我们失望地发现局面似乎并无改观。还有一个-0(1111),而且加法也不与正数加法兼容,比如:

0011 + 1100 = 1111 ( 3 + (-3)= -0,本应该是0的。)。

再仔细看看,0与-0的区别在哪里?我们稍微乐观点就可以意识到,0000与1111的差距只是差一个1 ?不是吗,1111+1=0000 !于是,补码定义呼之欲出了。

对正整数取反之后再加1 (补码运算规则)

现在我剩下的工作只需要重新考察,在这种预算规则下,刚才两个问题解决了没有?首先,还是看数字的表示范围:0000~0111(0~7,不变),负数1000~1111表示的是:-8~-1 。细心的同学就会立即发现问题说,哎,且慢,怎么多了一个-8出来?不着急,大家只需要对0000~0111这8个数逐个用补码规则求反就会发现,我们得不到1000这个数字,也就是说1000肯定不是-1~-7之间的数。而且运用一般二进制整数的加法来算,-1 (1111)加 -7 (1001) = 1000,那么1000不就刚好是-8么?多了-8出来,刚好-0就没有了。好消息之一!剩下就是继续检查,这种补码运算是否跟原定义的加法相容了。具体例子大家稍微动动笔就知道了。

补码是一个基本概念,在我们讲解这个基本概念的时候,大家往往只是“生吞”定义,然后声讨这些所谓的“理论”,声讨老师只教理论,不讲实践,痛心疾首自己学计算机学了好多好多年还不懂什么......讲完刚才这个例子,我只想问,补码是理论还是一种工程实践?如果它确实是理论(我也相信它是一种理论),如果没有丰富的实践基础可以得出来吗?这个理论难道不是扎根于实践而要深深地影响了实践吗?计算机科学就是这样一种源于实践而要影响实践的学科,而我没有见过不源于实践的理论,也没有见过不应用于实践的理论。

最后用一句Hamming的名言结束本注记(在我的课件中有):The purpose of computing is insight, not numbers.


P.S. 关于补码,如果上面的不想看或者因为我写得不好而不懂,可以记住以下最简单的理解补码的方法。一个n比特的数,范围是-2^{n-1} 到 2^{n-1} - 1,共有2^n个数,请注意它们都是mod 2^n的结果。其中所有的 -x的补码就是2^n - x !

例子:一个8比特的-7写为二进制原码是-00000111,二进制补码就是100000000 - 00000111 = 11111001,即为00000111的取反加1 !

这篇关于关于二进制补码的若干注记的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/338526

相关文章

如何将二进制文件流转化为MockMultipartFile文件

《如何将二进制文件流转化为MockMultipartFile文件》文章主要介绍了如何使用Spring框架中的MockMultipartFile类来模拟文件上传,并处理上传逻辑,包括获取二进制文件流、创... 目录一、名词解释及业务解释1.具体业务流程2.转换对象解释1. MockMultipartFile2

使用Python将长图片分割为若干张小图片

《使用Python将长图片分割为若干张小图片》这篇文章主要为大家详细介绍了如何使用Python将长图片分割为若干张小图片,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录1. python需求的任务2. Python代码的实现3. 代码修改的位置4. 运行结果1. Python需求

通信工程学习:什么是2ASK/BASK二进制振幅键控

2ASK/BASK:二进制振幅键控         2ASK/BASK二进制振幅键控是一种数字调制技术,其全称是二进制振幅键控(Binary Amplitude Shift Keying)。该技术通过改变载波的振幅来传递二进制数字信息,而载波的频率和相位则保持不变。以下是关于2ASK/BASK二进制振幅键控的详细解释: 一、2ASK/BASK二进制振幅键控的基本原理 1、振幅键控:

1 模拟——67. 二进制求和

1 模拟 67. 二进制求和 给你两个二进制字符串 a 和 b ,以二进制字符串的形式返回它们的和。 示例 1:输入:a = "11", b = "1"输出:"100"示例 2:输入:a = "1010", b = "1011"输出:"10101" 算法设计 可以从低位到高位(从后向前)计算,用一个变量carry记录进位,如果有字符没处理完或者有进位,则循环处理。两个字符串对

Leetcode67---二进制求和

https://leetcode.cn/problems/add-binary/description/ 给出的两个二进制,我们可以从最后开始往前运算。 给当前短的一位前面补充0即可。 class Solution {public String addBinary(String a, String b) {//给的就是二进制字符串 最后一位开始遍历 如果没有就补充0?StringBuil

二进制的匹配问题

最近做了点搜索和背包的题目,发现这个二进制的匹配很是好用,所以写一篇二进制的匹配来作为自我总结; 首先我们要知道二进制的运算符,和他们的运算规则; ABA&BA|BA^B00000010111001111110 运算符有三种‘&’ , ‘|’ ,  ‘^'  或,且,异或,运算的规则在表中可以看到,想想这个规则我们可以做很多事情! 首先,每个十进制的数都会对应一个唯一的二进

概率DP (由一道绿题引起的若干问题。目前为一些老题,蒟蒻的尝试学习1.0)

概率DP: 利用动态规划去解决 概率 期望 的题目。 概率DP 求概率(采用顺推) 从 初始状态推向结果,同一般的DP类似,只是经历了概率论知识的包装。 老题: 添加链接描述 题意: 袋子里有w只白鼠,b只黑鼠,A和B轮流从袋子里抓,谁先抓到白色谁就赢。A每次随机抓一只,B每次随机 抓完一只后 会有另外一只随机老鼠跑出来。如果两个人都没有抓到白色,那么B赢。A先抓,问A赢得概率。 w b 均在

二进制方式安装Helm

二进制方式安装Helm 官网:https://helm.sh/ 1、下载安装包 wget -L https://get.helm.sh/helm-v3.16.0-rc.1-linux-amd64.tar.gz 2、解压 tar -xf helm-v3.16.0-rc.1-linux-amd64.tar.gz 3、移动到/usr/local/bin/目录下 mv linux-am

输入两个整数m和n,计算需要改变m的二进制表示中的多少位才能得到n。

/*** 输入两个整数m和n,计算需要改变m的二进制表示中的多少位才能得到n。* 思路:第一步求这两个数的异或,第二步统计异或结果中1的位数*@author: Administrator*@date: 2017-1-13 下午09:39:25*/import java.util.Scanner;public class Solution4 {public int CountDifference

原码、反码、补码新解

世界上有10中人,一种懂二进制,一种不懂二进制。我们习惯了十进制计数,乍看到二进制,有点别扭,认识后慢慢发现它的神奇:有点一生二,二生万物的意思。十进制和二进制的部分对应关系如下: 小范围的十进制运算,我们操练起来麻麻溜溜的,二进制的运算相信你也不差,然,碰到十进制转二进制的运算就有点蒙圈了。 计算机 CPU 的运算器只实现了加法器,没有实现减法器。但,我们可以通过加上一个负数来实现减法运