带着问题学习(二进制数据)
- 32位是几个字节?
- 01011100对应的十进制是多少?
- 00001111左移两位结果是多少?有什么规律?
- 以补码形式表示的8位二进制数11111111,十进制为多少?
- 二进制和十进制有什么区别?
为什么要使用二进制?
IC.png 上图展示了一个较为简单集成电路的实例,而电脑就是由大量的集成电路芯片组成的,较为熟悉的CPU就是一个十分复杂的集成芯片。
上图中的每一个管脚只有两种状态,分别是通电和不通电,那么这两种状态就可以对应二进制中的0和1,这就是为什么电脑中需要二进制进行运算。
二进制值能表达的含义
image.png二进制能够表示这么多种类的数据格式,归根结底就是在计算机中所有的数据都是以数值的形式存储的,它们唯一的区别是在解析的时候不同,不同的数据格式有着不同的解析方式。
二进制和十进制的转换
- 二进制是一种计数方式
-
二进制值不仅仅是一个数
image.png
上图展示了一个简单的浮点数和二进制数之间的转换。
二进制的运算
二进制表示负数
在计算机中,是如何使用二进制表示负数呢?这就需要做一些硬性规定了,为了简单起见,我们拿一个char类型的数据类型举一个简单的例子。众所周知,一个char类型在计算机内存中占据8个bit,并且它的最高bit是用来表示正负号的,我们想知道-3的二进制char类型是什么样子,该怎么办呢?其实很简单,-3的二进制就是+3的二进制取反加1,过程如下:
3的二进制为:00000011
00000011取反为:11111100
11111100加1为:11111101
所以11111101就是-3的二进制表示。
我们可以再举一个例子,比如我们想知道-128的二进制表示,那么根据上面的过程:
128的二进制为:10000000
10000000取反为:01111111
01111111加1为:10000000
所以10000000就是-128的二进制表示。
相信通过上面的两个例子,您会对二进制表示负数有一个较为深刻的了解,如果您还不是太了解,我们再举一个简单的减法运算,比如10-7=?,我们知道,在计算机中,是没有减法运算的,它只有加法运算,所以我们不得不把上式改写为:10+(-7)=?,这样才能被计算机直接计算。现在的问题就是如何找到-7的二进制表示,和上面的方法一样:
7的二进制表示为:00000111
00000111取反为:11111000
11111000加1为:11111001
所以-7的二进制为:11111001
而10的二进制为:00001010
所以10+(-7)=00001010+11111001得出100000011共9bit,但是我们的数据类型是char,它只有8bit,所以不得不把最高位1舍弃,得到10+(-7)=00000011的值为3,和我们用十进制算的结果一模一样。
相信大家通过这几个例子,会对二进制表示负数以及计算机中对减法是如何操作了吧!!!
按位运算符
C语言提供了6个位操作运算符。这些运算符只能作用于整型操作数,即只能作用于带符号或者无符号的char、short、int、long类型:
- & 按位与(AND);
- | 按位或(OR);
- ^按位异或(XOR);
- << 左移;
-
右移;
- ~按位求反(一元运算符)。
二进制的按位与运算符(&)
只有两个位都是1的时候,这时的结果才是1,其它所有情况的结果都是0,比如:
1 & 1 的结果是:1;
1 & 0 的结果是:0;
0 & 1 的结果是:0;
0 & 0 的结果是:0。
二进制的按位或运算符(|)
只有两个位都是0的时候,这时的结果才是0,其它所有情况的结果都是1,比如:
1 | 1 的结果是:1;
1 | 0 的结果是:1;
0 | 1 的结果是:1;
0 | 0 的结果是:0。
二进制的按位异或运算符(^)
只有两个位不相等的时候,这时的结果才是1,其它所有情况的结果都是0,比如:
1 ^ 1 的结果是:0;
1 ^ 0 的结果是:1;
0 ^ 1 的结果是:1;
0 ^ 0 的结果是:0。
二进制左移
假如有一个char类型的变量,它的值为3,那么它的二进制表示为:00000011,分别左移1位、2位和3位,我们看得到的数值是多少!
00000011左移1位,得到00000110,它的值为6;
00000011左移2位,得到00001100,它的值为12;
00000011左移3位,得到00011000,它的值位24,;
从上面不难得到这样的一个规律,就是在不溢出的情况下,左移几位,就表示原来的数乘以2的多少次幂。
二进制右移
逻辑右移:我们把左边全部补0,不考虑符号位的右移称为逻辑右移。
二进制的右移就不像二进制左移那样简单了。我们先看一个例子,还是以一个char类型的变量为例,它的值为-128,让它右移2位,如果按照左移的规律,那么-128右移2位的值应该是-128除以2的2次幂,即-32。那么我们下面来右移一下看看。我们再推倒一次-128的二进制表示:
128的二进制表示为:10000000(这里我们先不考虑最高位表示正负号,只是考虑数值的大小);
10000000取反后为:01111111;
01111111加1为:10000000;
所以-128的二进制表示为10000000。
假如我们还是按照左移的方式右移,那么10000000右移2位位00100000,很显然这不是一个负数,因为负数的最高位是1,这不是我们想要的结果,我们称这样的右移为逻辑右移。
算术右移:左边补的数和符号有关的右移称为算术右移。
我们还是拿char类型的变量,值为-128来举例子。从上面知道-128的二进制表示为:10000000。那么它算术右移2位是11100000,11100000是-32吗?一般人不好看出来,不过没关系,我们推倒一下-32的二进制不就行了嘛!!!
32的二进制表示为:00100000;
00100000取反后为:11011111;
11011111加1为:11100000。
所以-128算术右移后的二进制11100000值就是-32。
无论是逻辑右移还是算术右移,它们都有存在的意义。在单片机编程中,比如跑马灯程序的编写,就有可能需要逻辑右移,但是这些又不是数值,更不是负数,它只是一些简单的数据。
二进制的按位求反运算符(~)
取反就是将0变成1.将1变成0,比如:
~1 的结果是:0;
~0 的结果是:1。
二进制数表示浮点数
关于浮点数的计算,这里有一个比较好的参考。
二进制表示浮点数
我们大概了解计算机中的浮点数是IEEE制定的一套表示方法,它的表示形式是科学计数法,如果想深入了解浮点数的表示请参考上面的链接,也可以自行查其它的资料,这里我们就不做深入讲解了。
由于计算机表示的浮点数大多数都是不精确的,只有部分小数是精确的(比如0.5、0.25、0.125等等),所以对于我们程序来说,重点要做的是:
- 不使用浮点数直接进行运算,而是使用整数进行运算,得到结果后,再除以相应的倍数,这样得到的结果才比较可靠;
- 在误差允许的情况下可以直接使用浮点数进行运算。
网友评论