• 什么是Complement(补码)?


    大学上过计算机原理课程的朋友都接触过补码这个概念,不过当时书上所教授的内容都是以二进制作为前提,即所谓的2的补码(2's Complement)。近来看TCP/IP Volume 1时,又接触到“1的补码”这个概念,忽然发现其实还不太明白补码到底是什么意思,故查阅资料记录之。

    资料来源:维基百科

    术语解释:Radix —— 基数,在本篇文章的范畴内等价于“进制”

    定义:给出长度为n的数值y,则y的以基数b的补码为: bn - y   (即 b的补码)

    水平有限,翻译的比较拗口,不过公式还是很简洁的,实际上补码从定义上来说并没有什么难懂的地方。不过有些地方需要加以说明,补码这个概念是建立在进制(即基数)的基础上的,至少在计算机科学的术语中,补码定义中的基数b是一定等于当前进制的,也就是说以上定义可以简化为

    给出长度为n的数值y且该数值为b进制,则y的补码为: bn - y

    下面以十进制的数作为例子

    给出数值y = 1234,很明显长度n = 4,基数b = 10(你说不知道10从哪来的?论审题的重要性)

    根据补码的定义那么 y的补码为:104 - 1234 = 8766

     

    用途:补码的作用是什么呢?你走运啦,补码的用途很专一 —— 用加法操作来代替减法操作

    听起来匪夷所思,你几乎要脱口而出:“不可能!!!”,不过按照国际惯例,我们先来看看到底怎么回事吧

    这里要引入另一个很简单但是英文又很有bigger的术语: 缩小基数补码 (diminished radix complement),看到 diminished 这个词我立马打个激灵,想起了久未谋面的缩小增量排序(diminished increment sort),啥?你说老师没教过这个?噢,它的另一个名字叫希尔排序,它是。。。咳咳,不好意思跑题了。

    缩小基数补码实际上就是 (bn - 1) - y,就是说你可以通过往缩小基数补码上加个 1 来得到基数补码,也就是说

    bn - y = (bn - 1) - y + 1

    是不是想大喊一声:这TM不是废话么??

    这个概念有什么用?其实在纯数学的范畴内,这个纯属多余,没有任何用处。然而到了我这个年纪,就会明白一切看起来无意义的东西,肯定一定必须存在一个让它拥有意义的上下文环境。在本文内,这个环境就是“一个数值的长度”,你要知道在数学范围内,你想把一个数写多长就有多长,但是在计算机内数值长是固定的,譬如Java语言的int数值长度为32位,你无法用32位的数去表示33位数,当然34位就更不行了!

    回到基数b这个关键字上面来,还是以十进制数为例子

    假设数值长度为固定的4,给出数值y = 1234,如果说你真的要按照定义在计算机内去获得补码,你是做不到的,因为根据定义补码为104 - 1234,然而104  = 10000,已经超出了4位数所能表示的范围,你明白了么?缩小基数补码就是为了能在固定的数值长度中去获得补码,所以退一步海阔天空啊 

    1. 104 - 1 = 9999
    2. 9999 - 1234 = 8765
    3. 8765 + 1 = 8766

    然而,聪明如你一定发现了,说是补码的用途是用加法代替减法,可是在以上第二步获得补码的关键步骤里,不还是要进行减法??这有毛区别?哈,这个就是最让人兴奋的地方,在二进制世界里,你不需要再用减法了,下面以二进制为例子

    给出数值y = 1011,那么很明显,按照最新的补码求解步骤,补码 = ( 24 - 1 ) - 1011 + 1,猛然一看,这哪里履行了补码的承诺,用加法代替减法?那么我们就以二进制的视角去看

     y    =  1011

    24 - 1   =  1111

    实际上你已经发现了,这个缩小基数补码是固定的——给定计算机数值长度n,则缩小基数补码可以直接写出:pppp...ppp(n个p,p = 进制 - 1),而关键的

    1111 - 1011,这一步实际上已经不需要作减法操作了,直接对 y 取反再加上 1 就能得到补码了(是不是对“取反加一”感到特别耳熟?你是个上课听课的好孩纸),在此不得不感谢伟大的二进制!需要再次声明下,这么流畅的操作只有二进制能完成,其他进制想要获得补码,依然需要减法。

    终章:在神奇的二进制世界中,获得一个数的补码只需要简单的取反再加上一就可以了。那么最后我们来看看,补码到手之后,又怎么能代替减法呢?

    假设需要求解 x - y ( x >= y),那么分为以下步骤

    1. 求得y的补码 bn - y
    2. x - y = x + ( bn - y ) = x  - y +  b (这一步用补码的加法代替了原数值的减法)
    3. 显然 x  - y +  bn >= bn,然而bn已经超出了数的表示范围(overflow),直接被丢弃了,最后的结果就等于x  - y

     1的补码:这个世界是没有1进制的,所以1的补码是一个缩小基数补码,也就是直接对一个二进制数值取反

  • 相关阅读:
    【C++缺省函数】 空类默认产生的6个类成员函数
    iOS 关于 UIKit 专栏应该写在最前面的话
    openssl之EVP系列之8---EVP_Digest系列函数具体解释
    二进制中1的个数
    UVA 548(二叉树重建与遍历)
    Leetcode Best Time to Buy and Sell Stock III
    javascript new Date()函数在不同浏览器上返回不同的值
    【网络流】 HDU 3468 Treasure Hunting
    树莓派玩耍笔记1 -- 开箱 & 安装系统以及简单配置
    POJ 1195 Mobile phones (二维树状数组)
  • 原文地址:https://www.cnblogs.com/PI3141592657/p/7134474.html
Copyright © 2020-2023  润新知