布尔代数

“if语句”一节讲过,a<b<c不表示b既大于a又小于c,那么如果想要表示这个含义怎么办呢?可以这样:

if (a < b) {
	if (b < c) {
		printf("b is between a and c.\n");
	}
}

我们也可以用逻辑与(Logical AND)运算符表示这两个条件同时成立。逻辑与运算符在C语言中写成两个&号(Ampersand),上面的语句可以改写为:

if (a < b && b < c) {
	printf("b is between a and c.\n");
}

对于a < b && b < c这个控制表达式,要求a < b的值非0并且b < c的值非0这两个条件同时成立,整个表达式的值才为1,否则值为0。也就是只有两个条件都为真,它们做逻辑与运算的结果才为真,有一个条件为假,则逻辑与运算的结果为假,如下表所示:

表 4.2. AND的真值表

ABA AND B
000
010
100
111

这种表称为真值表(Truth Table)。逻辑与的操作数是以非0表示真以0表示假,而运算结果是以1表示真以0表示假,我们忽略这些细微的差别,在表中以1表示真以0表示假。C语言还提供了逻辑或(Logical OR)运算符,写成两个|线(Pipe Sign),逻辑非(Logical NOT)运算符,写成一个!号(Exclamation Mark),它们的真值表如下:

表 4.3. OR的真值表

ABA OR B
000
011
101
111

表 4.4. NOT的真值表

ANOT A
01
10

逻辑或表示两个条件只要有一个为真,它们做逻辑或运算的结果就为真,只有两个条件都为假,逻辑或运算的结果才为假。逻辑非的作用是对原来的条件取反,原来是真的就是假,原来是假的就是真,这个运算符只有一个操作数,称为单目运算符(Unary Operator),以前讲过的加减乘除、赋值、相等性、关系、逻辑与、逻辑或都有两个操作数,称为双目运算符(Binary Operator)

关于真值的逻辑运算称为布尔代数(Boolean Algebra),以它的创始人布尔命名。在编程语言中表示T值和F值的数据类型叫做布尔类型,在C语言中通常用int类型来表示,非0表示T,0表示F[8]。布尔逻辑是写程序的基本功之一,程序中的很多错误都可以归因于逻辑错误。以下是一些布尔代数的基本定理,为了简洁易读,T和F用1和0表示,AND用*号表示,OR用+号表示(从真值表可以看出AND和OR运算确实有些类似*和+),NOT用¬表示,x、y、z的值可能是0也可能是1。

¬¬x=x

x*0=0
x+1=1

x*1=x
x+0=x

x*x=x
x+x=x

x*¬x=0
x+¬x=1

x*y=y*x
x+y=y+x

x*(y*z)=(x*y)*z
x+(y+z)=(x+y)+z

x*(y+z)=x*y+x*z
x+y*z=(x+y)*(x+z)

x+x*y=x
x*(x+y)=x

x*y+x*¬y=x
(x+y)*(x+¬y)=x

¬(x*y)=¬x+¬y
¬(x+y)=¬x*¬y

x+¬x*y=x+y
x*(¬x+y)=x*y

x*y+¬x*z+y*z=x*y+¬x*z
(x+y)*(¬x+z)*(y+z)=(x+y)*(¬x+z)

除了第1行之外,这些公式都是每两行一组的,每组的两个公式就像对联一样:把其中一个公式中的*换成+、+换成*、0换成1、1换成0,就变成了与它对称的另一个公式。这些定理都可以通过真值表证明,更多细节可参考有关数字逻辑的教材,例如[数字逻辑基础]。我们将在本节的练习题中强化训练对这些定理的理解。

目前为止介绍的这些运算符的优先级顺序是:!高于*/%,高于+-,高于>、<、>=、<=,高于==、!=,高于&&,高于||。写一个控制表达式很可能同时用到这些运算符中的多个,如果记不清楚运算符的优先级顺序一定要套括号。不过这几个运算符的优先级顺序是应该记住的,因为你需要看懂别人写的不套括号的代码。

习题

1、把代码段

if (x > 0 && x < 10);
else
	printf("x is out of range.\n");

改写成下面这种形式:

if (____ || ____)
	printf("x is out of range.\n");

____应该怎么填?

2、把代码段:

if (x > 0)
	printf("Test OK!\n");
else if (x <= 0 && y > 0)
	printf("Test OK!\n");
else
	printf("Test failed!\n");

改写成下面这种形式:

if (____ && ____)
	printf("Test failed!\n");
else
	printf("Test OK!\n");

____应该怎么填?

3、有这样一段代码:

if (x > 1 && y != 1) {
	......
} else if (x < 1 && y != 1) {
	......
} else {
	......
}

要进入最后一个else,x和y需要满足条件____ || ____。这里应该怎么填?

4、以下哪一个if判断条件是多余的可以去掉?

if (x<3 && y>3)
	printf("Test OK!\n");
else if (x>=3 && y>=3)
	printf("Test OK!\n");
else if (z>3 && x>=3)
	printf("Test OK!\n");
else if (z<=3 && y>=3)
	printf("Test OK!\n");
else
	printf("Test failed!\n");


[8] C99也定义了专门的布尔类型_Bool,但是没有广泛应用。