Skip to content

L1-07 逻辑表达式

逻辑表达式

布尔类型

布尔是计算机科学中的逻辑数据类型,以发明布尔代数的数学家乔治·布尔为名。它是只有两种值的原始类型,通常是真和假。

在之前列出的数据类型表中,我们介绍过了布尔类型 bool ,从表中我们可以看到,布尔类型能存储的数值只有 0 和 1 。实际上,这和布尔类型的值代表的意义有关。布尔类型是逻辑数据类型,只有真或假这两种可能,相对应的就是 0 或 1 这两个数值。其中 0 代表 false (假), 1 代表 true (真)。

c++
bool flag = true;

关系运算符

关系运算符是用来判断参与运算的两个量之间是否满足某种关系的,如果满足对应的关系运算结果就为 1 (true),否则为 0 (false)

符号关系示例
>大于5>3true1
>=大于等于3>=3true1
<小于5<3false0
<=小于等于3<=5true1
==等于3==3true1
!=不等于3!=3false0

尽管大多数关系运算符都和数学中的不等号相同或相似,但一定要记住关系运算符的运算结果是 0 或 1 ,对应着相应的关系是否成立。

例如:运算式 5<3 得到的结果为 0 ,因为 5 不小于 3 。

为了更好的理解关系运算符,我们来看下面一段代码:

c++
#include<bits/stdc++.h>
using namespace std;
int main()
{
    int a = 4, b = 7, c = -5;
    cout << (a < b) << endl;
    cout << (a > b) << endl;
    cout << (c <= 0) << endl;
    cout << (c >= 0) << endl;
    cout << (5 != 9) << endl;
    cout << (c != -5) << endl;
    cout << (a == 4) << endl;
    cout << (b == 4) << endl;
    return 0;
}
运算式所用运算符是否满足对应关系运算结果
a<b<1
a>b>0

上述程序的运行结果:

text
1
0
1
0
1
0
1
0

逻辑运算符

逻辑运算符的使用对象是布尔值, C++ 中的逻辑运算符有三种。

运算符专有名解释数学逻辑符号
&&and 与并且
|or 或或者
!not 非不符合¬

逻辑运算符被用来串联多个关系表达式,形成最终的逻辑表达式。

逻辑运算与

先来看这样一个问题:

妈妈:如果你今天做完了数学和语文作业,那你就可以玩游戏

  1. 两个作业我都没做完,可以玩吗?
  2. 我只做完了数学作业,可以玩吗?只做完了语文呢?
  3. 我做完了数学作业和语文作业可以玩吗?

妈妈的话就是一个很简单的用逻辑运算符 "与" 连接的逻辑表述。我们不难分析出,只有当“做完数学作业”和“做完语文作业”同时成立时,“做完数学作业和做完语文作业” 才成立。因此妈妈说的话可以用 && 这样来转述:

如果你今天做完了数学作业&&做完了语文作业,那么你就可以玩游戏。

可以看到,逻辑运算符&&起到一个“并且”的作用。我们发现“做完数学作业”和“做完语文作业”都像我们的关系表达式一样,只有真(成立)或假(不成立)两种取值。

因此不难想到逻辑运算符&&在计算机语言中的用法:

text
x <= b && x >= a
a != 3 && b == 4
a == b && a != 2 && b == 3
text
条件1 (或布尔类型的值)&& 条件2(或布尔类型的值)
条件1 && 条件2 && 条件3....条件 n

(注:上面的条件可以是任何值为 bool 类型的语句或量)

逻辑运算和关系运算一样,都只有 true 和 false 两种结果

而对于逻辑运算&&,只有当&&连接的两个语句都为 true 时结果才为 true ,否则为 false

例如:

text
a=3,b=5;  a!=3&&b==5 值为false(0)
a=4,b=9;  a<=b&&a!=b 值为true(1)
a=2,b=3;  a!=b&&0  值为false(0)
a=2,b=2;  a==b&&1  值为true(1)

逻辑运算或

再来看几个问题:

妈妈: 如果你今天做完了数学或语文作业,那就可以玩游戏

数学和语文作业我都没做完,可以玩吗?

我只做完数学作业,可以玩吗?只做完语文作业呢?

我做完了数学作业和语文作业可以玩吗?

不难发现根据这次妈妈的表述,只要语文作业和数学作业完成一项,就可以去玩游戏了。也就是说,这要“完成数学按作业”和“完成语文作业”这两个条件中任意一个成立,“做完数学作业或做完语文作业”这整句话就成立了,这就是或的概念。

因此妈妈说的话可以用逻辑运算符 || 如下转述:

如果你今天 做完了数学作业 || 做完了语文作业,那就可以去玩游戏。 可以看到逻辑运算符 || 在这里起到了“或者”的作用。

逻辑运算符 || 和逻辑运算符 && 的用法类似,我们可以写出下面这些逻辑语句:

text
a<b||a==b
a==5||a==7
a!=3||b!=5||a==b

使用格式与&&基本相同:

text
条件1||条件2
条件1||条件2||条件3...条件n

只要有一个条件成立,整个语句的运算结果即为 true(1) 。

若所有条件都不成立,则整个语句的运算结果为 false(0) 。

例如:

text
a=4,b=6;  a<3||b>6 的值为false
a=4,b=6;  a==4||b>6的值为true
a=4,b=6;  a==4||b==6的值为true

逻辑运算非

还是从妈妈的话讲起。

妈妈: 如果你今天没有看过电视,那你就可以玩游戏

可以看到根据这一次妈妈的表述,当“看过电视”不成立时,就可以去玩游戏了。逻辑运算符!和这里的“没有”作用相同,加上之后可以改变语句的成立性。

比如在这里,“看过电视”如果是成立的,那么“没有看过电视”就是不成立的;“看过电视”如果是不成立的,那么“没有看过电视”就是成立的。

妈妈说的话可以这样改写:

如果你今天看过电视,那你就可以玩游戏。

我们不难发现,和其他两个逻辑运算符不同,! 并非用来连接两个条件,而是用在一个条件前改变这个条件的成立性的。

可以写出下面这些逻辑语句:

text
!(a<=b)
!(a!=5)
!(a>5||b<3)

使用格式为: ! 条件

例子
a=3a==3 的值为 true!(a==3) 的值为 false
a=3,b=4a>b 的值为 false!(a>b) 的值为 true
a=3,b=4a>5||b<3 的值为 false!(a>5|b<3) 的值为 true

多选题

以下 4 个逻辑表达式的书写格式正确的包括?

A. && a<=b

B. a<=b||a==c

C. a<=b!a==c

D. a==3&&b==4

题解

BD

1、&&、||:运算放在两个式子的中间起连接作用,排除 && a<=b 2、!:放在式子前面,起取反的作用,排除:a<=b!a==c 因此选:a<=b||a==c和 a==3&&b==4

单选题

下面几个逻辑运算式的结果为:

  1. a=3,b=4a=3,b=4 a<=b&&a!=5a<=b&&a!=5
  2. a=4,b=5a=4,b=5 a==4||b!=5a==4||b!=5
  3. a=3a=3 !(a<=5)!(a<=5)

A. true true true

B. false true false

C. false true true

D. true true false

E. false true false

题解

D

1、a=3,b=4 a<=b=true a!=5=true (a<=b&&a!=5)=true。 2、a=4,b=5 (a==4)=true (b!=5 false) = (a==4||b!=5)=true 3、a=3(a<=5)=true!(a<=5)=false

单选题

假设 A=true,B=false,C=true,D=true,逻辑运算表达式 A∧B∨C∧D 的值是( )。

A. true

B. false

C. 0

D. 1

E. NULL

题解

A

A∧B=false,C∧D=true,false∨true=true

逻辑表达式

用逻辑运算符将关系表达式或逻辑量连接起来的有意义的式子称为逻辑表达式。逻辑表达式的值是一个逻辑值,即 true 或 false 。

c++
#include<bits/stdc++.h>
using namespace std;
int main()
{
    int a = 4, b = 7, c = -5;
    bool flag = true;
    cout << ((a < b) && (a > c)) << endl; //逻辑表达式1
    cout << ((a > b) || flag) << endl; //逻辑表达式2
    cout << !(c <= 0) << endl; //逻辑表达式3
    return 0;
}

单选题

下列逻辑表达式有错的是(    )

A. a <= b && !c

B. b == a || b == 5

C. && b > c

D. !a

题解

C

&&和||必须左右两边都必须连接关系式或者逻辑变量

单选题

设 a 为 int 类型变量,不能正确表达数学关系  3<a<5 的 C++ 语言表达式是(    )

A. 3 < a < 5

B. a == 4

C. a > 3 && a < 5

D. !(a <= 3) && !(a >= 5)

题解

A

3 < a < 5正确表达方式:3 < a&&a < 5

单选题

下列表达式中,表达整数n能被3整除的是:(    )

A. n % 3 != 0

B. n % 3 == 0

C. (n % 3 == 1 || n % 3 == 2)

D. !(n % 3 == 0)

题解

B

能被3整除就是对3取余等于0,因此选n%3==0

逻辑关系等价

逻辑表达式中,有很多是完全等价的,我们来列举一些。

表达式等价表达式
a < b!(a >= b)
a > b!(a <= b)
a != ba > b || a < b
a == b!(a > b) && !(a < b)

除了等价关系,还有很多逻辑相反的关系,下面列表中, a ba b 均为 bool 变量:

表达式取反逻辑
a && b!a || !b
a || b!a && !b

单选题

若x=5,则逻辑表达式 x>3&&x<10 的值为真。

A. 正确

B. 错误

题解

A

逻辑表达式 x>3&&x<10 的相反表达式为 x<=3||x>=10。

习题

课堂练习:条件输出4

编程实现输入两个整数a,b,当a≥b时,输出2,否则输出0。

你知道如何不使用 if,switch以及 3 目运算符,来解决这个问题么?

输入格式

输入两个正整数a,b

输出格式

输出一个数表示结果。

输入样例

text
4 6

输出样例

text
0

数据范围

对于10%的数据,1≤a,b≤100。

c++
#include <bits/stdc++.h>
using namespace std;
int main() {
  int a, b;
  cin >> a >> b;
  cout << (a >= b) + (a >= b) << endl;
  return 0;
}

利用 a≥b 的条件判断为真时,返回 1 ,否则返回 0 这个特性。把 (0,1) 变为 (0,a) ,那么直接将结果乘以 2 即可,即输出 (a≥b)∗2 。

课后作业:条件输出5

编程实现输入两个整数a,b,当a≥b时,输出a的值,否则输出0。

你知道如何不使用 if,switch以及 3 目运算符,来解决这个问题么?

输入格式

输入两个正整数a,b

输出格式

输出一个数表示结果。

输入样例

text
4 3

输出样例

text
4

数据范围

对于10%的数据,1≤a,b≤100。

c++
#include <bits/stdc++.h>
using namespace std;
int main() {
  int a, b;
  cin >> a >> b;
  cout << (a >= b) * a << endl;
  return 0;
}

利用 a≥b 的条件判断为真时,返回 1 ,否则返回 0 这个特性。把 (0,1) 变为 (0,a) ,那么直接将结果乘以 a 即可,即输出 (a≥b)∗a 。

头脑风暴

烙饼排序

有一摞烙饼,我们想要把它们按从小到大的顺序排好,比如起初从上到下的大小分别是 [3,5,2,4,1] ,我们想要把它们排成 [1,2,3,4,5] 。我们每次的操作仅限于从一摞烙饼中抽出一张,放到烙饼堆的最上面。我们想要用最少的次数达到目的。你知道该怎么做吗?

例子:比如 [2,4,5,1,3] 这一摞烙饼中,我们先后把 3,2,1 分别抽出来放到顶上,烙饼就排好序啦。

我们考虑 5 是不能移动的,因为一旦将 5 拿出,放到最上面,后面所有的烙饼都要拿出来。

在 5 确定不动的情况下,我们看 4 是否要移动,如果 4 在 5 的后面,一定要移动,否则无法完成排序,如果在 5 的前面,我们可以将 5 和 4 之间的数字抽出来,这样 4,5 就是有序的。

再来看 3 与 4 的位置关系,情况与 4,5 相同,如果在 4 前面则无需移动,否则一定要移动。

以此类推,到最小的数为止。

最终方案是从大到小,从后向前,找到 5,4.. 这样的序列,一旦找不到某个数,那么这个数及以前的都需要移动,移动方法就是从大到小逐个抽出来放在最上面即可。