前言

我们都知道计算机内部是使用二进制来进行运算的,那么你对于二进制转换为其它进制或者其它进制数转换为二进制数是否熟练于心呢?

与我们现实中的十进制不同,计算机内部使用二进制表示(一般我们书写用十六进制来展示,这样比较简洁,相比一大串01来说),也可以用ASCALL码表示,但它们都有一个问题:表示负数并不明显。所以我们需要了解另一种计算机内部的表示方法:二进制补码。

对于求解二进制的补码,你是否存在诸多的疑问?例如为什么可以采用对原码求反码,之后加一得到补码的操作?为什么可以用十六进制10000减去负数的绝对值就得到负数的二进制补码表现形式?如果你有这些疑问的话,让我们一起来走进01世界吧(如果仅仅对二进制补码不解,请直接跳转到后半部分)。

进制转换技巧一窥:

1、对于二进制和十六进制的转换:

     首先对于二进制和十六进制来说我们都是直接转换的,毕竟每四位二进制就可以表示一位十六进制数,而十六进制数也是每一位表示四位二进制数。他们之间的转换诀窍就是将0~15的二进制十六进制表转换熟记于心即可。

2、对于二进制补码的转换:

  1. 对于无符号数(正数)来说,二进制的补码就是它本身,没有什么特别的,所以这里重点强调有符号数(负数的表示)
  2. 对于无符号数(负数)来说,计算机内部只有一种表示方法(就使用补码表示),但是有求解补码有两种方法,实际上我们自己手写的数字逻辑计算是一种,计算机内部计算又是一种:
  • 我们将其转换为十进制数(绝对值),然后转换为二进制得到原码,再对原码取反(也就是0变1,1变0),然后加一就得到了二进制补码--->这里我将它命名为方法一,它其实就是计算机内部进行的计算方式。
  • 我们先用十六进制表示这个数的无符号数(也就是取绝对值然后表示为十六进制数),然后用10000H(表示十六进制)减去这个数,就得到了该数的字长二进制补码表示--->命名方法二(这个才是最开始科学家想出来的计算方式,要了解这个方法,我们需要了解模的概念,可以直接关注下半部分。因为计算机内部是不可能进行取绝对值,减法运算的,所以计算机科学大佬们就想出了方法一的办法,让计算机来求解。)

    ------->我们可以用方法二来计算,用方法一来验算,这样做出来的结果一定就是正确的(但是我更加推荐直接方法二计算即可,因为它本来就是我们求解二进制补码的方法,只是为了让计算机可以理解我们的做法,才使用方法一这样的反码加一方式)。

一、二进制和十六进制一定要记住(或熟练导出)一表

十进制 十六进制 二进制
0 0 0
1 1 1
2 2 10
3 3 11
4 4 100
5 5 101
6 6 110
7 7 111
8 8 1000
9 9 1001
10 A 1010
11 B 1011
12 C 1100
13 D 1101
14 E 1110
15 F 1111

把这个表写出来其实很简单,只需要记住十进制与二进制的转换即可,我们知道从右到左二进制的权值为2的幂次方,即1,2,4,8,16,那么对于十进制数13来说,转换为二进制数就可以看做是8+4+0+1即四位二进制最高位8为1,第二位为1,第三位为0,第四位为1,那么就是1101。对于4来说,直接100即可。所以此表就已经熟记于心了。

二、转换过程

十六进制 十进制 二进制补码
    0110
  -27  

识别正负数(有符号无符号数)技巧:

  • 对于十进制数的识别我们从小就知道,有负号就为负数
  • 对于二进制的识别,符号位即最高位为1(左边第一位)就为负数,反之为正数
  • 对于十六进制来说,如果左边第一位在[1,7],那么为正数(这个很好理解,因为十六进制和二进制随意转换,那么我们知道对于四位二进制来说,1~7最高位均为0,到8之后最高位就是1了),反之为负数。

(1)我们知道二进制补码0110,一看就知道是正数,那么二进制和十六进制是直接转换的,所以就有十六进制的数为6,那么十进制的数也是6。

(2)我们知道十进制数-27,首先我们用方法二将它取绝对值27,然后求27的十六进制数为1B(小技巧就是27=16+11,所以第一位为1,第二位就直接为B)。用十六进制100减去1B(这里也可以用10000字长,但100长度也就够了的)得到十六进制为E5,之后十六进制和二进制直接转换,那么就为1110 0101。

答案:

十六进制 十进制 二进制补码
6 6 0110
1B -27 1110 0101

三、转换原理总结:

方法二用某个适当的2的幂的数作为减数(例如上面的十六进制100)减去负数的绝对值的十六进制数就得到了该有符号数的十六进制。因为任何时候对一个数求二进制补码,得到结果再对该结果求其二进制码就得到原数。用长度为字的数N表示有:

N = 10000 - (10000 - N)

所以我们将负数取绝对值在用100减的时候,其实得到的十六进制数就是该负数的二进制补码数。

如果我这样解释为什么可以这样计算负数的补码,你一定一头雾水,因为它仿佛只是告诉你一个结论,没有起因,也没有任何的中间过程。你所知道的手动计算负数的补码,无非就是让十六进制100减去这个数的绝对值。但why???

首先我们理解一个原则,计算机肯定是为人类服务的,所以它内部的思想当然也是我们先有的思想,才想到如何在计算机内部实现,其次我们要理解,计算机肯定和数学密切相关的。那么我说这个话有什么用呢?我们慢慢看:

上面说计算机大佬们的方法就是用10000减去负数绝对值从而得到二进制补码(当然,这里的负数绝对值和10000当然是十六进制啦)。如果你尝试使用原码、反码、补码的方式来解释这个方式,那你就走错方向了,因为我们总是先有前一个方式,才在计算机内部用反码的形式来求解(毕竟内部元件直接异或运算)。那在绝对值,加加减减的过程中,可能你会回忆起小学的补数操作,因为相加为最大数的两个数互为补数(小学的10、100等10^n),那么你想一下,相加为100000的两个数,如果互为补数(姑且那么说),那么我是不是可以直接这样去思考呢?当然是的!

在密码学的时候接触到了“模”的概念,例如:钟表是有12个刻度的,现在是7点,我想将它减小到3点钟,你肯定有两个方法:一是你直接逆时针转动4个刻度到达3点(几乎所有人都会那么做吧);二就是顺时针转动8个刻度,也可以到3点钟。这里12就是模,也就是说7-3=4等价于12-4=8。这个时候你可能有了一点概念,那我们再来一个例子,例如90-10和90+90(相当于90+(100-10)))如果不考虑100进位的话,其实他们都是等价于80的,模就是100;对于10-80和10+(100-80)来说,不考虑100进位那么就是-70和30,显然两者不是一回事,于是圣贤们就想出用一半表示正数,一半表示负数的方式,也就是说,我们将100分为两份,一份为0~49,另一份为50~99(它其实表示的是-49~-1,注意这里有大小对应关系,即99代表-1),也就是98就是-2。是不是和我们的二进制表示一样,只是不同的是,老师会告诉我们最高位是符号位,表示正负,例如8位二进制有1000 0001即129,也可以看做是二进制补码表示的-1。

那么上面我们看到互为补数的数在模的范围内做减法,可以将“X-Y”的减法运算变为“X+Y的补数”的加法运算

我们回到计算机的二进制数、十六进制数来看,如果想要表示负数,那么我们可以表示为负数绝对值的补码形式。在这里,我们的10000其实就是相当于模(它是2的n次幂,相当于能够表达的最大的数值),而我们的运算肯定是在模的范围内,那么就可以看做是上面互为补数的数在模的氛围内是可以有负数变为绝对值补码形式的。为什么说10000相当于模呢,我们从上面隐约知道,模就是最大的(近似这么看),例如时钟的模就是12。0到100的数模就是100,那么对于计算机来说,模肯定就是2的n次幂,那么到底是多少呢?

例如,8位二进制数一共可以表示2^8次方==256个数,即256就是8位二进制的模。照这么说,我们对于256之间的数的减法就可以看成是加上绝对值补数的加法。可是我们8位不是全部表示正数的,我们需要分出一半来表示负数,那么0~127就是128个数来表示正数,而-128~-1就表示负数部分。绝对不可以超过这个数字,否则8位的运算就溢出了,计算机内部会进行溢出的异或运算检测。

那么我们来计算一下-128的补码,不就是256-|-128| = 128,而128的二进制不就是1000 0000。结合一下最初提出的十六进制的10000来计算,其实很好理解的,因为我们的模不都是2^n次幂吗?例如8位二进制的模就是2^8次幂==256,它的十六进制表示不就是100吗?而其它的位数进制的模也都是10000(后面根据位数进行添0操作,例如8位可以表示两个16进制数嘛,那100不就是最大的数值嘛,其实不够就在1后面添加0就好)。

现在回到我们上面的例子,总结一下不就是一句话吗?——负数的表达方式就是它绝对值的补数。

因为计算机内部不可以进行绝对值等运算,所以我们才使用原码、反码、加一的操作来达到我们上面算法的结果。就是我们手动计算十进制-27的时候,可以直接对它绝对值的十六进制求补码。而计算机内部是这样的:首先-27的原码是1001 1011,然后除符号位之外都01置换,即得到11100100,然后加一得到1110 0101。和上面我们手算的一对比,一样的对吧。

当然有些老师求负数补码也有自己的技巧,例如对于-27来说,得到27的原码有0001 1011,之后从右往左除第一个遇到的1不变之外,其它都取反,也可以得到-27的补码,即1110 0101。但是它们的原理其实都是计算机大佬的负数的表达方式就是绝对值的补数的这个概念。对于10进制的说来说,我们总是熟悉10、100补数,对于2进制的数来说,我们也要熟悉十六进制的100、10000等模的概念。

总结:

第三次修改之后这个就是最后的版本了,希望你能够理解补码的表示形式,对于我们计算来说它是一回事,对于计算机内部来说,又是另一回事。但是不得不说,补码的形式真的很好用,果然计算机大佬就是多呀。

小问题:

发了文章之后,有人问为什么二进制负数能够表示的范围的绝对值总是比正数多一,其实这个也不是什么困难的事情。这里我就举一个8位二进制的例子,我们都知道它能够表示的范围是-128~-1,0~127。因为我们上面说过,8位可以表示256个数,为了能够表示负数,所以我们各取一半来表示正负数,即正数表示为0~127,而负数不就是-128~-1吗?

在计算机内部,-1不就是对应1111 1111,它的真值不正是255吗?和我们上面所解释的原理是一致的。至于-128那么在计算机内部肯定是表示1000 0000啦。

希望对你们有所帮助,有问题可以在讨论区一起讨论哦~

进制转换小技巧之让你重新认识二进制补码(大师,我悟了)!!!相关推荐

  1. 如何使用Qt开发一个进制转换小工具

    本游戏使用Qt5.8开发 这是一款进制转换小工具,比如十二进制的源数据15,如果您选择目标进制7进制的话,那么按下转换按钮,程序会输出[23]:程序的逻辑原理大概如此:首先把输入通过一系列算法转换成b ...

  2. VB 进制转换大全(十进制、十六进制、八进制、二进制、二进制流)互转

    模块包含了下面的各种转换: 二进制转十进制 二进制转化为八进制 二进制转化为十六进制 八进制转化为十进制 八进制转化为二进制 八进制转化为十六进制 十进制转二进制 十进制转化为八进制 十进制转化为十六 ...

  3. Java算法学习:java进制转换(十进制转八进制,十进制转二进制,十六进制转八进制)

    java进制转换(十进制转八进制,十进制转二进制,十六进制转八进制) 这几天在复习C语言的数据结构栈和队列那一章的时候,看到利用栈的特性FILO实现的进制转换十分简洁 想起了java中实现栈的操作十分 ...

  4. Java做一个进制转换小工具

    通过swing和awt实现的一个简单的进制转换工具 可以进行数之间的进制转换 只有两个类 所有代码都放在https://github.com/13337356453/BHD_Converter 可自行 ...

  5. 进制转换 和 正数负数——原码,反码,补码

    进制转换 定义:进制也就是进制位,对于接触过电脑的人来说应该都不陌生,我们常用的进制包括:二进制.八进制.十进制与十六进制,它们之间**区别在于数运算时是逢几进一位.比如二进制是逢2进一位,十进制也就 ...

  6. 进制转换算法 (C语言实现一个简单的二进制转换工具) ------- 算法笔记010

    进制转换算法概念 其核心是利用栈的存储结构性质,进行数据的入栈出栈时的计算,让后将计算好的数据存入另一个栈内,最后再出栈输出.由于栈的先进后出特性,最后输出的顺序和输入的顺序是一样的.具体如上图. 栈 ...

  7. 计算机进制转换小程序

    背景:由于最近下载了很多数据集,基本都很大,但windows上都是以kb为单位进行显示,脑子有时无法快速估计数据集所栈内存,所以写了个简单的小程序进行转换. 计算机进制转换规则: 转换规则:bitX8 ...

  8. Java进位制转换小技巧

    在进行进位制转换时,若是自己写一个函数出来,是比较麻烦的,此时我们就可以调用封装类(Integer.String)的方法,来更容易地操作进位制. 将其他进制转十进制: Integer.valueOf( ...

  9. c语言小数点进制转换,新手求教,关于含小数的二进制转换成十进制

    该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 #include #include void main() { int i=0,n,j,a[20],b[20],k,c=0; double m,x,d; ...

最新文章

  1. recyclerview item点击无效_让你彻底掌握RecyclerView的缓存机制
  2. 5.3 使用tensorflow搭建GoogLeNet网络 笔记
  3. 《犯罪心理学》读书笔记(part7)--犯罪心理的主观差异(中上)
  4. UVa11988 Broken Keyboard(练习链表使用)
  5. 在过渡到Agile中的十种错误
  6. 计算机视觉领域常见期刊和会议,计算机视觉领域常见期刊和会议
  7. java filter注入_如何在Java Filter 中注入 Service
  8. netty大白话(四)
  9. 使用java9的uuid生成方式,让uuid生成速度提升一个档次
  10. 修改CDH的HostName和IP
  11. Windows server2016 安装SqlServer2005 无法启动服务
  12. sqlite3命令行把.db文件导成.txt时报错及中文乱码
  13. w ndows7安不上HP1020,1020打印机驱动
  14. DOE软件测试工资,如何进行实验设计(DOE)
  15. 微信小程序:王者荣耀吃鸡气泡等等头像框DIY在线生成N种风格
  16. Python-[jieba库应用]-统计水浒传中人物出现次数
  17. C++ 多态性 (polymorphism)
  18. 网易im 服务器消息格式,基础消息功能
  19. NKOJ-3776 工资管理
  20. 论文解读:OMNI-DIMENSIONAL DYNAMIC CONVOLUTION

热门文章

  1. 软路由当文件服务器拒绝了连接,软路由服务器怎么设置方法
  2. github上的图片看不了,教你解决
  3. ulimit -c unlimited生成core文件
  4. CURL HTTP返回505
  5. 2023开学季哪款电容笔值得买?高品质电容笔品牌推荐
  6. 数据结构---二叉树的顺序结构及实现
  7. 达梦数据库(DM)的安装教程分享
  8. 科学中的直觉和反直觉
  9. C语言-海选高大中锋-PTA
  10. There are test failures.