二进制如何算减法(二进制下为什么能用补码来计算减法)

作者:Sotyoyo

来源:https://segmentfault.com/a/1190000038573204

二进制如何算减法(二进制下为什么能用补码来计算减法)(1)

学习目标
  1. 计算机中是怎么去描述一个"数"的?(本文有答案)
  2. 补码到底是什么?为什么要发明它?为什么用补码就可以计算减法?获得一个原码的补码的原理是什么?(本文有答案, 重点
  3. 怎么知道一个占n比特位的数,它所能表示的整数范围是多少?(本文没细讲)
  4. 什么是浮点数?怎么用二进制表示浮点数?什么是浮点数的精度?(下一讲)
对比一个时钟,来看二进制补码数据应该怎么在计算机内存储?
  • 在计算机的世界里,不论任何数据形式,只能用 二进制 表示和计算,因为作为开关的电信号仅有两种状态。二进制,简单来说我认为是一种计数规则,相比于我们从小学到大的十进制,二进制就是逢二进一。举例,5 (10) = 101 (2) ,5在十进制数当中算作一位,因为他只有一个"个位",而101 (2) 这个数字在二进制中算作三位,每一位都以电信号的方式存储在计算机的某个半导体内。我们这里的"位",就叫做1一个 比特位(bit) ,这很重要,它直接影响了数的表示范围。
  • 存储信息的半导体的个数是有限的,所以用来表示数的比特位也是有限的,我们不能随心所欲的无限扩张它,我们要尽可能的增大表示范围,又要控制数据的存储空间。举例,在Java中,一个int类型占据了4个 字节(Byte) ,再加上我偷偷告诉你1个字节等于8个比特,所以Java里int占32位:在脑海里的样子:0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000什么?不看虚的?那你瞧一瞧下面这张图!这,就是标题里面 问题1 的答案 -- 数据以一个个的电容信号存储在计算机硬件里面的某些半导体中,你仅可以想象它的样子(如上面的32个0) 。
  • 我在这里不想描述进制间是怎么转换的,这不是我们今天讨论的重点,感兴趣的话可以自行搜索。
整数的二进制表示和补码
  • 整数又分为正整数,负整数,零。如果想要简单的来表示 无符号整数 ,定义一个正整数占4个比特位的话,那么6 (10) = 0 2 3 1 2 2 1 2 1 0 2 0 = 0110 (2)在这种情况下,我们无法表示出负数,那么用这样的方法表示多少个非负整数?也就是 0000 (2) \~ 1111 (2) 也就是 [0 \~ 2 3 2 2 2 1 2 0 ] = [0 \~ 15] 也就是 2 4 个。可我就是想要表示-6怎么办呢?我们只能sacrifice掉一位男...额不对,是牺牲掉1个比特位。也就是说我们要拿出1个比特位来做符号位,0表示正,1表示负那么,同样一个 6:6 (10) = 1 2 2 1 2 1 0 * 2 0 = 0110 (2)一定要注意这次的计算方式和上一次的区别,少了一次对2 3 的计算!是因为这次存储数值的总共就三位,还有一位用作了符号位:符号位 数值位 0 110自然而然 ,我们会想到用 1110 (2) 来表示-6的二进制(我一定要先声明,这是一种 错误 :no_good:‍♂️的做法,请往下看完)这里出现了一个问题,如果我想让你计算 1-6=?/** 计算机没办法做减法,只能通过 1 (-6) 来实现1-6 **/ 0 0 0 1 1 1 1 0 1 1 1 1

你会发现结果是 -7, 这显然不对。(原因是第一位是用来表示正或负号,不能参与计算)

  • 为了解决这个问题,人们想出了补码的概念。当负数用二进制补码表示后,符号位能与有效值部分一起参加运算,减法运算可以转换为加法运算并且结果正确。原理呢?别急,看看下面这个家伙这是一个时钟,12进制。我们运用生活中的经验来回答以下几个问题:Q1.现在是8点,问5小时后是几点? 8 5 = 13 但是时钟上没有13点,所以你看到的是1点 Q2.现在是8点,问5小时前是几点? 8 - 5 = 3 3点!可是请问用加法怎么解决这个问题呢?这里我们可以用8 7来得到3点把8-5看作是时针从8点向前拨动了5个小时,回到了3的位置,但是他也等同于把时针从8点向后拨动7个小时,到达了3的位置上。然后你心里面一定会有疑问 ️小学数学告诉我们8-5=3,可是你来给我解释解释8 7为什么等于3!$$\begin{cases} \text{-5 0 = -5}\\ \text{0 = 12} \ \ \text{在时钟只有一个的情况下(只有1个比特位时)0 = 12 (可以看下时钟,0点也是12点,对吧?)} \end{cases}$$所以 -5 12 = 7 = -5可以看到,这里的-5等于了7,我们把12进制中的7和-5就称作是一组 互补数 ,用这样方法,可以做到加法代替减法,让计算机把符号位带入还可以正常运算如果你没看懂,那你听听我的另一种解释:8 7=15,但是时钟是一个12进制的工具,所以十进制的15 (10) 的实际表达是12进制的13 (12) ,但是由于我们只有一个时钟,就相当于我们只有一个比特位来存储13 (12) 这个数据,那么第二位"1"就 溢出 了,这个"1"相当于是被一个黑洞给吞掉了,我们根本没有办法去找回来,所以最后只剩下一个12进制的3 (12) ,所以最后8 7=3!
  • 那么,在二进制中,该怎么计算出 补码 呢?正数和0的补码就是该二进制本身,也就是 原码 。负数的补码则是将其对应正数的原码按位取反得到 反码 再加1。原理呢!我们假定现在用2个比特位来表示1个数,依葫芦画瓢,列出下面的不等式组:$$\begin{cases} \text{原码 补码 = 00}\\ \text{00 = 100} \ \ \text{只有2个比特位时} \end{cases}$$补码 = 100 (2) - 原码 = (11 (2) 01 (2) )- 原码 = 11 (2) - 原码 01 (2)而11 (2) - 原码是什么?仔细想一下,这不就是相当于是原码取反后的结果吗!写到这里,我想你终于可以弄懂 问题2 了吧?
小数的二进制表示
  • 小数可以拆成整数部分和小数部分,整数部分的表示方法在上面,小数部分应该怎么做呢?举例,十进制123.45表示成二进制如下图:具体的转换方式是:整数部分采用十进制转二进制方法进行小数部分乘以2,然后取整数部分。不断重复该操作直到 小数部分为0,或达到指定的精度
  • 你想要的只是岁月静好。但是呢,不是所有的小数都能转换有限位数的二进制小数。例如10进制0.2的二进制:0.2 x 2 = 0.4 00.4 x 2 = 0.8 00.8 x 2 = 1.6 10.6 x 2 = 1.2 10.2 x 2 = 0.4 00.4 x 2 = 0.8 00.8 x 2 = 1.6 10.6 x 2 = 1.2 1……不光岁月静好,我还送你天荒地老这是为什么呢?抛开数学概念,十进制中1的一半是0.5,二进制中1的一半是0.1;十进制中自然可以十等分形成小数,所有不能十等分的都是无限循环,同理二进制中只能二等分,所有不能二等分的自然都是无限循环。正如切蛋糕,二进制就像一把一次只能切一半的刀。
  • 讲了这么久,该表示表示了吧?所以, 理论 上,我们可以这样存储小数(以123.5为例):符号位 整数位 小数位 0 0111,1011 1000,0000但是,这种方法是不被采用的,实质上,被用来表示小数的东西叫做 浮点数
浮点数的二进制表示
  • 敬请期待
本文引用了
  • 为什么十进制小数转换成二进制有可能无限循环? 卫知 的回答
  • 浮点数在计算机中是如何存储的?
  • V (base) : 下标base代表进制数,V则代表了在该进制下的值表示。

作者:Sotyoyo

来源:https://segmentfault.com/a/1190000038573204

,

免责声明:本文仅代表文章作者的个人观点,与本站无关。其原创性、真实性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容文字的真实性、完整性和原创性本站不作任何保证或承诺,请读者仅作参考,并自行核实相关内容。文章投诉邮箱:anhduc.ph@yahoo.com

    分享
    投诉
    首页