二进制补码:Why & How

学习计算机原理或者语言的底层操作难免会遇到用二进制补码表示负数的问题。由于一些书本上对于采用补码的原因没有详细解释,很多人会认为这只是一种规定,但实际上采用补码是因为这种表示方法拥有实际的优势。而对于求补码的方法“按位取反再加一”,给出解释的资料就更少,本文试图给出二进制补码的优势和求法的简单解释。


Why

首先回答为什么要使用补码的问题。补码是一种计算机中负数的表示方法,当然,计算机中可以表示负数的方法不止补码一种,但目前几乎只有补码这种方法得到了广泛运用。数字的表示方法影响到数字在计算机中的存储和运算,下面对比三种可行的负数表示法来说明补码在这两方面的优势。

  • 带符号的原码

    最容易想到的负数表示方法就是将一个二进制位用来表示数的符号,例如规定数字的最高位是0时为正数,是1时为负数,把这一最高位加在负数绝对值的二进制表示(也即原码)的前面。这种方法非常直观易懂,例如310可以被表示为00112而-310可以表示为10112。我们平时在进行整数运算时可以把符号当作减号,但计算机执行简单的加法时并不会这样处理,以-310+310为例,计算机将00112+10112相加后得到11102=610从而产生了完全错误的结果。当然通过额外的电路或者程序可以让计算机像我们一样处理负号,但这会增加电路成本或影响性能。

  • 偏置数制

    为了解决运算负数在计算机中的运算问题,可以让存储的二进制值表示它的值减去某个数得到的数字。例如,对于三位二进制数,规定计算机存储的二进制数a实际上表示的是a-4对应的数字。这样0002不再表示010而是-410,而1002才表示010。这样的三位二进制数可以表示[-4, 3]范围内的所有整数,而由于并不存在需要额外处理的符号位,直接对偏置数制表示的二进制数进行加法得到的结果总是正确的。这种表示法的问题在于,要想得到存储的二进制数原来表示的数字,总要将其再加上某个数值——虽然稍显麻烦,但这已经比带符号原码在每次运算时都要处理符号要进了一大步。

  • 补码

    补码是一种兼具上面两种表示法特点和优势的数制。补码同样使用二进制数的最高位来表示符号,并规定最高位为1时表示负数。不同于带符号的原码的是,当表示负数时,补码采用偏置数制。例如,表示-410时,首先将-410+810得到偏置数1002,然后在前面加上符号位1得到11002,即是-4的四位二进制补码;正数的表示方法则与带符号的原码完全相同。注意这里所说的偏置数制与上述的略有不同,这里的二进制表示和实际数值差8而不是4,这是因为我们想利用低三位表示[-8,-1]范围的数。补码的正数和负数加法都很好理解,因为正数加正数或负数加负数并不涉及符号位的变化。而对于正数加负数,补码也能得到正确的结果,以-210+310为例,11102+00112=00012,注意到最高位因为来自低位的进位而由1变成了(1)0,最高位产生的进位溢出而被忽略,这样的溢出不会造成运算结果出错所以无需顾虑。补码表示法下的负数加上正数时,若正数大于等于负数的绝对值,将产生一个向最高位的进位而改变符号,从而保证了结果的正确性。你也许要为偏置数制争辩,尽管补码可以让正数容易得到,但负数却还是需要额外的运算。下面将展示这种计算可以是相对简单的。

How

至于如何从负数的原码得到补码,几乎所有的教科书都给出了“绝对值按位取反再加一”这一捷径,但关于其中道理能阐明的却很少。对最高位取反很容易理解,因为绝对值为正,需要变换符号才能表示负数,我们着重讨论低位的情况。以4位二进制补码为例,除最高位外的低3位实际上表示该负数a比-8大了多少(例如-210的补码11002的低三位1002=610表示-2比-8大6),也即:

a+8=a-(-8)

换句话说,这是求该负数的绝对值比8小了多少:

a-(-8)=8-(-a)=8-|a|

不过我们更希望能用710去减掉a的绝对值,因为710是01112,而01112去减掉任意一个[110, 710]内的数(也即[00012, 01112]内的数)的差正好是被减数的按位取反(对于每一位,1-0=1;1-1=0)。但记住,我们要求的值是与8的差,如果用7去减就要再加一补回来:

8-|a|=7-|a|+1

这就是按位取反再加一的原理,尽管我们是用4位二进制补码来演示的,对于更高位数也很容易想象到推广的情形。 值得一提的是,虽然上面的分析是从方便我们计算的角度考虑的,但实际上“按位取反再加一”是为了方便计算机计算而产生的技巧(取反和加一都是很容易实现的操作),也同时是补码相对于其他两种表示法的优越性所在。

二进制补码:Why & How的更多相关文章

  1. 利用ZYNQ SOC快速打开算法验证通路(1)——MATLAB浮点数与定点二进制补码互转

    最近本人一直在学习ZYNQ SOC的使用,目的是应对科研需要,做出通用的算法验证平台.大概思想是:ZYNQ PS端负责与MATLAB等上位机数据分析与可视化软件交互:既可传输数据,也能通过上位机配置更 ...

  2. java基础 二进制补码

    二进制补码: 1.计算机系统的内部以二进制形式存储数据. 2.在Java程序中输入的十进制的数据都会被自动转换为二进制,Java内部也以二进制来进行数值运算,但返回的结果是十进制. 二进制补码的原理: ...

  3. 二进制补码除法——计算机底层整数除法模拟之Java实现

    前面讲到布思算法的计算机底层模拟的时候,我们是借助于一个可以储存.表示任意N位的二进制补码的BinaryQueue实现的,现在我们模拟计算机底层整数除法还是要借助于它: BinaryQueue类代码: ...

  4. Day05_C操作符及二进制补码计算

    回顾:  1.数据类型  2.二进制(八进制,十六进制) --------------------------------------------------------- 计算机中不可以使用负号表示 ...

  5. 任意N位二进制的补码实现——队列存放

    正在学习计算机组织与结构,为了写一些底层的算术操作模拟,比如一个二进制补码数的加减乘除,发现这很麻烦,因为不管是什么语言,都只提供了8位.32.64位等部分位数的补码形式,那么怎么实现任意任意位的补码 ...

  6. int abs(int number)函数有感: 求补码和通过补码求对应的整数 C++(增加:数字的二进制表示中1的个数)

    #include "limits.h" #include "math.h" int abs(int number) { int const mask = num ...

  7. 二进制原码、反码、补码以及Java中的<< 和 >> 和 >>> 详细分析

    1.计算机二进制系统中最小单位bit 在计算机二进制系统中: bit (位) :数据存储的最小单元. 简记为b,也称为比特(bit),每个二进制数字0或1就是一个位(bit),其中,每 8bit = ...

  8. 一道int与二进制加减题

    int dis_data = 32769; if( dis_data > 0x7fff)  dis_data -= 0xffff; printf("%d\n",dis_dat ...

  9. WindowsPhone-GameBoy模拟器开发六--[转]指令系统实现必读:补码

    网上有同行写了些好文章,在此就不现丑了,贴上连接,放在这里为了补充系列的完整性 计算机为什么选用二进制补码 为什么补码重要?因为计算机中内存.寄存器里面存的数都是用补码表示的!

随机推荐

  1. cookie存在哪里???

    平时各位在做项目时多半时候都会用到客户端的cookie,可大家知道cookie是存储在哪里吗? 首先cookie失效分为2种: 1:设置过期时间失效(只要设置了过期时间cookie就会存储在硬盘里面) ...

  2. 5G-NR物理信道与调制-下行链路v1.1.0

    上接<5G-NR物理信道与调制v1.1.0>下行链路 References Definitions, symbols and abbreviations 帧结构与物理资源 通用函数 上行链 ...

  3. Leetcode 20题 有效的括号(Valid Parentheses) Java语言求解

    题目描述: 给定一个只包括 '(',')','{','}','[',']' 的字符串,判断字符串是否有效. 有效字符串需满足: 左括号必须用相同类型的右括号闭合. 左括号必须以正确的顺序闭合. 注意空 ...

  4. webpack环境配置2

    1.webpack安装 Step 1: 首先安装Node.js, 在1中已经详细介绍了. Step2: 在Git或者cmd中输入下面这段代码, 通过全局先将webpack指令安装进电脑中npm ins ...

  5. HTTP协议 有这篇文章足够了

    HTTP 协议详解 HTTP(HyperText Transfer Protocol)超文本传输协议.其最初的设计目的是为了提供一种发布和接收HTML页面的方法. HTTP是一个客户端(用户)和服务端 ...

  6. Object-C 银行卡,信用卡校验规则(Luhn算法)

    最近的项目中涉及到绑定用户的银行卡,借记卡.经过查找银行卡的校验规是采用 Luhn算法进行验证. Luhn算法,也被称作“模10算法”.它是一种简单的校验公式,一般会被用于身份证号码,IMEI号码,美 ...

  7. CSS+DIV自适应布局

    CSS+DIV自适应布局 1.两列布局(左右两侧,左侧固定宽度200px;右侧自适应占满) 代码如下: <!doctype html> <html> <head> ...

  8. Go coding in go way(用Go的思维去coding)

    本文是Tony Bai在2017年第三届GopherChina大会上所作,来源如下 https://tonybai.com/2017/04/20/go-coding-in-go-way/ 一.序 今天 ...

  9. Codeforces Round #295 (Div. 2) B. Two Buttons 520B

    B. Two Buttons time limit per test 2 seconds memory limit per test 256 megabytes input standard inpu ...

  10. HTML5 基础知识(1)——基本标签

    ## HTML**概念**:是最基础的网页开发语言(Hyper Text Markup Langage 超文本标记语言) > 1.超文本:超文本是用超链接的方式i,将各种不同空间的文字组织在一起 ...