当前位置: 首页 > 科技观察

关于二进制表示和补码计算的来龙去脉,入门后秒懂

时间:2023-03-13 03:04:21 科技观察

系统也是由0和1组成的。了解这两个简单但功能强大的数字可能是您作为软件开发人员的入门学习的一部分。但是,大多数人对于二进制、二进制运算、原码、反码、补码还处于机械强制记忆阶段。特别是对于一些编码和计算,还处于模糊的理解阶段,例如:CPU是如何表示负数的?为什么可以用补码表示负数呢?为什么一个8位二进制数的最小值是-128而不是-127?为什么CPU中的加法器可以和符号位一起运算呢?在这篇文章中,我们将讲述最基础的内容,帮助大家理解二进制计算的相关内容。看完这篇文章,不仅知道了,当然还能知道为什么!PS:这个有点高调,why的最后一部分要涉及到数学证明的层面。本文不涉及证明过程。二、从十进制到二进制1、十进制是数学计算能力强的国家,10以内的加减法要在幼儿园就可以完成。如果你不属于这个范围,就说明你在假幼儿园。让我们快速回顾一下有关十进制算术的一些基础知识:每个数字包含从0到9的数字;每个数字的数量是其右边数字的10倍;两个数相加时,同一个数位,如果以上数之和大于等于10,则前进1位,即:满十进制一;具体来说:右起第一个数字(个位)的数字代表多少个1;右起第二位(十位)的数字代表有多少个10;右起第三位数字(百)代表多少个100;右数第四位(千位上的数字)代表多少个1000;十进制数可以用后缀字母D表示,也可以省略。例如:十进制数1234中,个位为4,十位为3,百位为2,千位为1(通常取自一个放在最右边)),每个数字上的数字是其右侧的十倍。如下图:十进制数据,又称十进制表示法。2.二进制那么二进制呢?直接套用上面十进制的概念,然后把10换成2(先忽略符号位):每一位包含的数是0和1;每个数字中的数字,是右边数字的2倍;两个数相加时,如果同一个数中的数之和大于等于2,则前进1位,即:全二比一;具体来说:从右边第一个数字上的数字代表多少个1;右起第二位数字代表多少个2;右起第三位数字代表多少个4;四位数字代表多少个8;记住几个重点:二进制数只包含0和1两个数,相加时满2。在十进制中,我们给每一位数字起一个特殊的名字(个位、十位、百位……),但是在二进制中没有类似的命名。二进制数用后缀字母B表示,例如:二进制数1111B,权重用图片表示如下:换算成十进制数就是15(1*8+1*4+1*2+1*1=15)。在二进制中,每一位称为一位(bit)。如果用8位来表示一个二进制数,则最小值为0000_00000,最大值为1111_1111;如果用16位来表示一个二进制数,最小值为0000_0000_0000_0000,最大值为1111_1111_1111_1111。(为了便于观察,每4位之间加了一个分隔符)在早期的计算机中,8位处理器非常普遍,所以给它起了一个特殊的名字:Byte。一个16位的二进制数是2个字节,又称为:字(Word)。3、扩展为十六进制的原理还是一样:直接把十进制的10换成16:每一位所包含的数字是0到9,A到F;每一位数是右边数位的16倍;两个数相加时,如果同一位上的数之和大于或等于16,则前进1位,即:全16进制1;具体来说:从右数第一位的数字代表有多少个1;右起第二位数字代表16的个数;右起第三位数字代表256的个数;右数第四个数字代表多少个4096?在十六进制中,0到15需要16位数字来表示,0到9比较好办,但是10到15需要找一些符号来表示,所以人们想到了用字母A、B、C、D、E、F分别代表10到15这六个数字。十六进制数据用后缀字母H表示,在某些情况下也可以用前缀0x表示,本质上是一样的。例如:十六进制数1A2BH(或者写成0x1A2B),每一位的权重如图:转为十进制数为6699(1*4096+10*256+2*16+11*1=6699)。4、扩展到任意基数的原理还是一样的:直接用目标基数替换十进制的10,比如基数5:每一位包含的数字都是0到4;每个数字中的数字是其右边数字的5倍;两个数相加时,如果同位数字之和大于或等于5,则前进1位,即:满五合一;具体来说:从右数第一个个位数中的数字代表了多少个1;右起第二位数字代表多少个5;右起第三位数字代表多少个25;右数第四位数字上的数字代表多少个125;再看一张图加深印象:三、从十进制加法到二进制加法1、十进制加法不用多说,只有2条规则:两个数,同一位上的数相加;每位数字相加结果为十进制整数一;例如:在个位上:4+8,结果是12,但是十进制里没有12,所以向左边高位进1,个位上剩下的:12-10=2.十位上:7+2,加上一个进位1,结果是10,但是十进制没有10,所以向左边高位进位1,十位就变成:10-10=0.百位:1加进位1,结果为2。2.二进制加法第0位:0+0,结果为0;第一位:1+0,结果为1;第2位:1+1,结果为2,但是二进制中没有2,所以需要将1进位到左边的高位,所以第二位保留2-2=0。第三位:1+1等于2,加上进位1,结果为3,但是二进制中没有3,所以需要向左边的高位进位,所以3-2=第3位留1。第4、5、6、7次计算同理。3、第0位十六进制加法:E+C,结果为26,但是十六进制中没有26,所以需要向左边的高位进1,所以第0位就剩下26-16=A。第1位:A+1等于B,再加进位1,结果为C,即十六进制中的数。四、将负数计算转换为正数计算1、原码原码(真实形式)是计算机中数字的二进制定点表示方法。原码表示在数值前加符号位(即最高位为符号位):正数为0,负数为1(0有两种表示方式:+0和-0),其余位表示值的大小。比如用8位(8位二进制数)表示一个数,+11的原码是0000_1011,-11的原码是1000_1011。2、我们都知道CPU有加法器,好像没听说过“减法器”。比如计算5+8,转成二进制计算:我们再计算一下减法:5-8,对于CPU来说,只会计算5+8,不会计算5-8。但是你可以换个思路,把减法变成加法5+(-8),这样就可以算出来了?于是计算机先驱们发明了反码:正数的反码:保持原码不变;反码:原码中符号位不变,其余全部取反(-8的原码为1000_1000,反码为:1111_0111);所以5+(-8)的计算过程就是:这时候就完美解决了减法题,那么乘法(多加法)、除法(多减法)题也就解决了。至于如何从数学的角度去证明,就得问那些数学家了!3、新问题:0怎么表示?我们现在可以总结一下反码的表示范围(记住:第一位是符号位):Positive数的表示范围:0000_0000~0111_1111,即十进制的+0~+127的128个数;负数表示范围:1000_0000~1111_1111,即十进制-127~-0的128个数;你有没有发现任何问题?:为什么会有+0和-0这两个数字?而且它们的编码也不一样:+0对应0000_0000,-0对应1111_1111。CPU虽然是傻子,让它为所欲为,但是CPU最不能容忍的就是不确定性!我们都知道+0==-0==0,它们是同一个数,但是在二进制代码中,其实有两个代码来表示同一个数。伟大的计算机先驱又做了一个决定:正数不变,负数整体减1。也就是说:符号位不变,数值整体加1,如下:这样就成功解决了-0和+0的问题!现在一个8位的二进制可以表示范围:-128~127,并且没有任何重复、遗漏的数字。由于每个二进制表示的值都发生了变化,因此继续称其为补码是不准确的。这时候,给它们起一个新的名字:补码,也就是说:上图变成这样:补码的总结代码定义:正数的补码:保持原码不变;负数补码:原码中符号位不变,其余先取反,再加1(例如:-8的原码为1000_1000,补码为1111_1000);此时,我们只是解决了二进制码的表示问题,那么:补码可以直接参与运算吗?运行结果会出现什么问题?4、看一下补码的计算问题:假设现在时间是1:00,但是你的手表进水了显示3:00,请问现在怎么把时间调到1:00?方法一:将时针逆时针转动2小时(3-2=1);方法二:将时针顺时针转动9小时至12点,再转动1小时(3+10=1);对于时钟表盘,每12小时为一圈,可以认为:-2==10,-1=11,-3=9,同理:-2==10,-2==22,-2==34,...可以看到规律是:-2,10,22,34这些数对12取模得到相同的数(正数)。在数学中,当两个整数除以“同一个整数”时,如果得到的余数相同,则这两个整数全等。表盘上的12是“同一个整数”。可见这是一个“溢出”的系统。数字-2、10、22、34在表盘上代表的是同一个数字,所以这几个整数是全等的。也就是说:计算的时候,可以用数字10、22、34来代替-2,替换后的计算结果是一样的。那么对于一个8位的二进制数,最多只有8位。在计算过程中,如果最高位产生了进位,就会被丢弃,所以也是一个“溢出”的系统。那么这里的“同整数”是什么呢?从前面的内容可以看出,用补码表示的8位二进制数所代表的范围是-128~127,一共256个数,所以如果对256取模,得到相同的余数,那么这些数字是一致的数字。例如:-2和254对256取模,余数相同,所以是全等数,那么在计算时,可以用254代替-2。那么让我们通过计算3+(-2)来验证它。(1)用全等数计算3+(-2)==3+254=257257超出最大表示范围,所以溢出,结果为257模256,结果为1。(2)直接使用计算3的补码的补码为0000_0011,-2的补码为1111_1110。计算时,符号位也参与运算:结果也为1,也就是说:在二进制计算中,用补码来计算,“自然”满足“同余定理”。细心的读者可能已经发现:-2的补码表示和254的二进制自然表示是一样的!这种“自然”是巧合吗?还是计算机前辈设计的结果?!五、作为本文的结尾,我们探索了计算机系统的软件基石:二进制系统。主要目的是帮助大家理解二进制的表示和计算。