前言
有一个整数,想知道它的二进制表示中有多个1,你会怎么做?本文将带大家深入学习下二进制以及它的各种运算,一步步的研究出这个问题的解决方案,欢迎各位感兴趣的开发者阅读本文。
前置知识
在解决这个问题之前,我们需要先了解下什么是二进制。
二进制
在计算机的世界里,只有0和1,也就是二进制。
符号数
在二进制中,数被分为有符号数和无符号数。
对于有符号数而言,符号的正、负机器是无法识别的,但由于“正、负”恰好是两种截然不同的状态,如果用“0”表示正,用“1”表示“负”,这样符号也被数字化了,并且规定将它放在有效数字的前面,即组成了有符号数。
因此,在二进制中使用最高位来表示符号。
- 最高位是0,表示正数。
- 最高位是1,表示负数。
二进制的最高位就是其第一位,例如:10000001100,它的最高位就是1。
对于无符号数而言,它表示的数其范围都是正数,所有位都用于表示数的大小。
有符号数的性质
对于有符号数而言,它有6个性质:
- 二进制的最高位是符号位:0表示正数,1表示负数
- 正数的原码、反码、补码都一样
- 负数的反码 = 它的原码符号位不变,其它位取反(0 -> 1; 1 -> 0)
- 0的反码、补码都是0
- 负数的补码 = 它的反码 + 1
- 在计算机运算的时候,都是以补码的方式来运算的
原码、反码、补码
上述性质中,我们提到了原码、反码、补码,接下来我们来学习下他们究竟是什么样的数字。
- 原码,分为两种情况:
- 一个正数,按照绝对值大小转换成的二进制数
- 一个负数,按照绝对值大小转换成的二进制数,然后最高位补1
- 反码,也分为两种情况:
- 一个正数,它的反码与它的原码是相同的
- 一个负数,它的反码为该数的原码除符号位外,各位取反
- 补码,也分为两种情况:
- 一个正数,它的补码与它的原码也是相同的
- 一个负数,它的补码为对该数的原码除符号位外各自取反后,在最后一位加1
进制转换
我们要对二进制进行运算,需要先将十进制数转为二进制,因此我们需要先学习下十进制转二进制的方法。
十进制转二进制
将十进制转为二进制主要分为三种情况:
- 正整数转二进制
计算规则为:除二取余(直至商为0),然后倒序排列,高位补零。
知道规则后,我们举个例子,求一下80所对应的二进制数,如下图所示:
image-20211025213251590
计算机内部表示数的字节单位是定长的(字长),如:8、16、32、64位。因此当计算出来的二进制的位数不够时,需要在高位进行补0。
上述例子中,我们将80转为二进制数后,它的值为:1010000,字长为7,如果计算机的字长是64位,那么标准写法就是在它的最高位前面补57个0,我们用计算器来验证下,如下所示:
image-20211006101942620
- 负整数转二进制
在计算机中,负数是以原码的补码形式进行表达的,通过前面的学习,我们知道了想求负数的补码,就得先求出它的原码。
我们以-80
为例来计算下它的二进制码,步骤如所示:
- 求原码,如下图所示:
image-20211025213338223
- 求补码,如下图所示:
image-20211014233217872
至此,我们得到了-80
的二进制码:10110000
在正整数转二进制部分,我们讲了计算机是固定字长的,当计算出来的二进制位数不够时,正整数会在高位补0,负整数则会在高位补1。
我们用计算器来验证下我们计算出来的-80的二进制码是否正确,如下所示:
image-20211014233921705
- 小数转二进制
在二进制中,小数被称为浮点数,我们在将十进制小数转换为二进制小数时,需要以小数点为界限,将其拆分为整数部分和小数部分。
整数部分转为二进制,我们在前面已经讲过了(即除2取余)
小数部分转为二进制的方法为:乘2取整数部分,继续用小数部分乘2,直至小数部分为0(大多数情况下不会为0,需要确立精度)
我们以80.13
为例来计算下它的二进制码,如下图所示:
image-20211026003224757
计算机中用二进制来表示小数时,大部分十进制小数都不能精确的用二进制来表示,当表示这种小数时,最大精确多少位,取决于计算机的字长。
上图中,我们计算出了
80.13
的二进制码为01010000.00100
,我们精确到了小数点后5位。
我们用计算器来验证下是否正确。
image-20211026004819315
二进制转十进制
同样的,二进制转十进制也分为三种情况:
- 正整数转十进制
从二进制的最低位开始,给每一位标上序号,取出不为0位置的数的序号,将其作为2的次方进行计算,最后将结果相加。
我们以01010000
为例,求一下它的十进制数,如下图所示:
image-20211028233947922
- 负整数转十进制
前面我们学习了十进制负整数转二进制的方法,那么二进制转十进制,则需要倒着来算,我们以10110000
为例,步骤如下所示:
- 根据补码求原码
image-20211029001747628
- 除去符号位,对其他位按照正整数转二进制的规则进行计算,最后补上负号,如下图所示:
image-20211029002527261
- 小数转十进制
给小数点后每一位标上负序号(从-1开始),取出不为0位置的数的序号,将其作为2的次方进行计算,最后将结果相加。
我们以01010000.00100
为例,求出它的十进制数,如下图所示:
image-20211029231026693
经过前面的学习,我们知道了十进制小数转二进制时,大多数情况是无法得到精确值的,我们用80.13举例时,精确到了小数点后5位。
同样的,我们将二进制小数转换为十进制数时,也是无法得到准确值的,最终值也取决于精度,此处我们保留2位小数,四舍五入后就为
80.13
。