一、真值表与逻辑运算
- 真值表
真值表是什么呢?我们来看百度百科的定义。
表征逻辑事件输入和输出之间全部可能状态的表格。列出命题公式真假值的表。通常以1表示真,0 表示假。命题公式的取值由组成命题公式的命题变元的取值和命题联结词决定,命题联结词的真值表给出了真假值的算法。
这个看着很拗口是吧。我们来举个例子吧。比如我们的目的是明天出去玩,但是有几个条件,第一是否加班,第二是否晴天,我们把各种情况列在一起,就是一个真值表。
是否加班 | 是否晴天 | 是否出去玩 |
---|---|---|
是 | 是 | 否 |
是 | 否 | 否 |
否 | 是 | 是 |
否 | 否 | 否 |
在这里各种情况和最终结果就一目了然了。是否出去玩这个命题的结果就由是否加班和是否晴天两个变量共同作用。如果我们把里面所有的是都认为是真,用1代表,所有的否都认为是假,用0代表,那么就变成了这样。
是否加班 | 是否晴天 | 是否出去玩 |
---|---|---|
1 | 1 | 0 |
1 | 0 | 0 |
0 | 0 | 1 |
0 | 0 | 0 |
这就是一个真值表,表明了两个变量共同作用得到最终命题的结果。这个式子可以写成,只有当不加班并且晴天的时候才会出去玩。
我们将影响一个结果的因素列出来,用1表示真,用0表示假,就得到了真值表。真值指的就是表中每一项的真假。在计算机中我们一般考虑的是是真是假,大部分情况下我们认为0代表假,其他一切非0,比如1,或者其他正整数、负整数甚至小数都可以表示真。所以一般简单归类就是0和非0,也就是用1代表一切非0就好了。
- 逻辑运算
逻辑运算是什么呢?我们还是来看一下百度百科的定义吧。
逻辑运算又称布尔运算。布尔用数学方法研究逻辑问题,成功地建立了逻辑演算。他用等式表示判断,把推理看作等式的变换。这种变换的有效性不依赖人们对符号的解释,只依赖于符号的组合规律 。这一逻辑理论人们常称它为布尔代数。20世纪30年代,逻辑代数在电路系统上获得应用,随后,由于电子技术与计算机的发展,出现各种复杂的大系统,它们的变换规律也遵守布尔所揭示的规律。逻辑运算 (logical operators) 通常用来测试真假值。最常见到的逻辑运算就是循环的处理,用来判断是否该离开循环或继续执行循环内的指令。
逻辑运算又称布尔运算,因为是布尔发明的。简单的说,就是基于真值表的运算,通过对运算过程中所有变量的真值的推导得到结果。逻辑运算一般结果只有真或者假,也就是1或者0。这段话还有一点要注意,也就是逻辑运算运用在电路上,如果你的初中物理学的还可以,那么理解起来会很容易的。
最基本的逻辑运算,与、或、非。其他的运算都是在这三个基础上做排列组合。
与运算
与运算用and或者&&表示,运算需要两个运算数,比如1&&0,5&&10。与运算指的是只有当参加运算的两个数字都是真,结果才是真,其他一切情况都是假。与运算真值表:
C=A&&B
A | B | C |
---|---|---|
0 | 0 | 0 |
1 | 0 | 0 |
0 | 1 | 0 |
1 | 1 | 1 |
与运算的本质是什么呢?是两个开关串联。不知道你对初中电路还记得多少。与运算相当于两个开关串联在一起,只有全部都处于联通状态(也就是真状态),灯泡才能亮(结果为真),只要有一个是断开的(也就是假状态),灯泡就不亮(结果为假)。
或运算
或运算用or或者||表示,运算需要两个运算数,比如1||0,2||7。或运算指的是参加运算的两个数字至少有一个为真,结果就为真。或运算真值表:
C=A||B
A | B | C |
---|---|---|
0 | 0 | 0 |
1 | 0 | 1 |
0 | 1 | 1 |
1 | 1 | 1 |
或运算的本质是两个开关并联。至少有一个开关处于联通状态,灯泡就能亮,只有当两个都断开,灯泡才不能亮。
非运算
非运算用not或者~表示,运算只需要一个运算数,比如~1,~19。非运算指的是反转运算数的真值,真的变成假的,假的变成真的,一般来说我们喜欢把1变成0,0变成1,如果你喜欢也可以变成任何其他的非0数字。非运算真值表:
B=~A
A | B |
---|---|
0 | 1 |
1 | 0 |
非运算的本质是开关短路灯泡,如果开关没有联通,灯泡可以亮,如果开关联通,灯泡被短路,不能亮了(为防止把电池烧了,电路要加电阻,还记得吗?)。
其他逻辑运算
还有很多其他的逻辑运算,但都是这三种的组合,比如与或,就是先与再或,或非就是先或再非,只要细心,按照顺序算下来,都是没问题的。
- 逻辑运算在电路中的应用——逻辑电路
逻辑电路是最简单的数字电路,更复杂的还有带时序的组合电路,数字电路基本上就是纯粹的逻辑,与历史时刻的输入和时钟信号没有关系。
逻辑电路中使用的就是与、或、非、与或、与非等等逻辑。在电路中,一个基本的逻辑单元叫做一个门,比如与门、或门、非门、与或门等等,为什么叫门呢,我也不知道,大概是觉得输入进了这个门就变成了输出吧。所以用以实现基本逻辑运算和复合逻辑运算的单元电路也称为门电路。在电路中一般用这些符号,左侧代表输入,有几条线就是有几个输入,右侧代表输出,仔细观察可以发现,输出带有小圆圈的都是带非门的。
哦对了,在这里说一下异或和同或,异或指的是两个数字不同结果为1,相同结果为0,同或刚好放过来,相同为1,不同为0。
异或
A | B | C |
---|---|---|
0 | 0 | 0 |
0 | 1 | 1 |
1 | 0 | 1 |
1 | 1 | 0 |
同或
A | B | C |
---|---|---|
0 | 0 | 1 |
0 | 1 | 0 |
1 | 0 | 0 |
1 | 1 | 1 |
比如这就是一个很简单的逻辑电路,这是一个全加器电路,将输入A和B与进位Cin加到一起,输出这一位结果和下一位进位。看最下面那个式子,那就是这个电路要做的事情,数字逻辑有自己的符号。
二、位运算
好啦,学完了逻辑运算,我们来学位运算。位运算是什么?计算机中存储的任何信息都是二进制的,位运算就是以位为单位对数据进行处理,处理的逻辑和逻辑运算一样,就是对每一位依次进行逻辑运算。
与、或、非是最基础的三种位运算方式,但一般叫做按位与、按位或和非,指的都是一位一位进行运算,而不是整个数字作为真值来运算。
- 最基础的位运算-按位与、按位或、非
按位与
按位与一般用&符号表示,注意这里只有一个&,比如5&7,6&11,按位与指的是两个数字的每一位相与,只要有一个是0结果就是0,只有两个都是1才能是1。
我们以5&7为例,遵循同为1结果才为1的原则即可
按位或
按位或运算用|表示,注意只有一个|,比如11|20,按位或指的是两个数字每一位进行或运算,只要有一个1结果就是1,两个都是0结果为0
非
非运算一般用~表示,这个就只有一个,非指的是数字每一位都取反,0变成1,1变成0,比如~18
- 其他位运算
其他还有很多位运算方式,比如按位异或,按位同或,这些你应该可以直接理解了。这里要讲的是移位运算。移位分为左移和右移,在很多编程语言中右移更加复杂,比如c语言分为右移和循环右移,是基于数字在内存中的存储方式和你的需要来选择的。这里只是讲一下最简单的左移和右移的原理。
左移
左移一般用<<来表示,A<<B就表示要把数字A的每一位都向左移B位,比如3<<2
所有数字左移之后低位补0,高位溢出就溢出吧,你现在还不用考虑高位溢出该如何处理,就直接照抄就好了。3左移2位后变成了12,很神奇吧,3*2=12,准确的说是3*2^2=12,这就是左移的意义,左移多少位就相当于乘以2的多少次方,代码里经常这样,因为移位操作比乘法快,原理就是图上的,你把一个二进制数字左移,就相当于给每个数字所对应的权重增加了几次幂,所以最后这个数字加在一起就相当于乘以2的多少次幂。
右移
右移和左移是相对的,一般用>>表示,A>>B就表示要把数字A右移B位,这里涉及到一个问题,右移的话低位数字怎么办,这个你暂时不用考虑,我们先用低位为0的数字举例,比如16>>4
右移高位补0,因为这里的低位数字为0,所以可以毫无顾忌地右移。和左移相反,右移就相当于把数字除以2的若干次幂,道理很简单,右移就是把数字的位的权重降低,所以就变小了。16/2^4=1。
程序员一般用左移和右移来实现对2的乘法或者除法,因为移位的速度远比乘除法快得多。
右移会涉及到低位问题,c语言的处理是有两种处理方式,一种是右移>>,低位无条件舍掉,不要了,另一种是循环右移>>>,右侧的低位会被补充到左侧高位,但这样又会产生很多问题,等到时候你就会知道了,所以选择使用哪一种要很慎重。
三、总结
这一章讲了真值表,就是各种真假情况和对应结果的罗列,然后引出了逻辑运算,基本上掌握与或非三种最基本都就行,后面讲了位运算,位运算一部分是基于逻辑运算的,和逻辑运算一样,只要记住按位就好啦,最后讲了位移,这都是编程,尤其是底层系统编程常用的技巧,只要理解了就很容易掌握的。