AP计算机科学A复习:Unit 3 – Boolean Expressions and if Statements 选择结构和布尔表达式

AP计算机科学A复习:Unit 3 – Boolean Expressions and if Statements 选择结构和布尔表达式

我们经常需要根据实际情况来在多个选项中做决策。在不同的条件下,选择的解决方案就可以不同。这个单元里,我们将了解什么是程序编写里的「条件」,随后使用「if Statements」判断语句让程序可以根据不同的条件做出不一样的反应。

U3.1 boolean expressions 布尔表达式

我们在现实生活里经常对两件或多件事物进行比较,然后做出判断。比如选校时就会比较排名,选择排名较高的学校。

「boolean expressions」就是我们在程序写作里进行比较的手段。我们在编写程序时要先假设事物之间的关系,比如,假设 a 大学的排名大于等于 b 大学的排名。如果假设成立,则 boolean expression的值为「真 true」;如果假设不成立,boolean expression的值就为「假 false」。「boolean expressions」的值只存在「真」和「假」两种可能性。在刚才的例子中,如果 a 学校的排名真的大于等于 b 学校,就会得到「真 true」,反之,如果 a 学校的排名小于 b 学校,则得到「假 false」。看看这个例子:

我们输入了两个整数,a 的值为67,b 的值为58。输出语句中填写的「boolean expressions」布尔表达式是「 a >= b」,意思是假设 a 的值大于等于 b 。当程序运行时,输出语句访问布尔表达式,布尔表达式判断此时 a 的值是否大于等于 b ,因为 67 确实大于等于 58 所以假设成立,布尔表达式的运算结果最终为「true」,输出的结果即为「true」。

注意,在boolean expression中,我们用来假设事物之间的关系的符号和手写数学公式时用到的符号有一点点不同。现在我们来更具体的了解布尔式的写法,在你的Eclipse 里面逐个运行尝试下面的语句:

  • 「等于 == 」 以及 「不等于 != 」
		System.out.println(6 == 6); // 假设:6等于6
		System.out.println(6 != 6); //假设:6不等于6

第一句话假设 6 等于 6,因此boolean expression 写作「6 == 6」。运行这个语句时,计算机判断发现6 真的等于6,假设成立,因此这个boolean expression的值为「true」。第二句话假设 6 不等于6,写作「 6 != 6」。当程序运行时,计算机判断发现6 不等于6 的假设并不成立,因此这个boolean expression的值为「false」。

在Java编程中,所有常见数据类型的数据都可以被「==」或者「!= 」比较。比如,你还可以用它们来判断字符串里面的内容是否相同,在自己的Eclipse里面尝试一下。还要注意,不要混淆赋值符号「=」和判断相等关系的关系运算符「==」。

  • 「大于 >」和「小于<」,「大于等于 >=」和「小于等于 <=」
		System.out.println(6 > 6); // 假设:6大于6
		System.out.println(6 >= 6); //假设:6大于等于6
		System.out.println(3.14 < 3); //假设:3.14小于3
		System.out.println(3.14 <= 7); //假设:3.14小于等于7

在你的Eclipse里先运行上面的语句,看看这些boolean expression的值都分别是什么。第一句话假设6大于6,实际上6 并不大于6,二者相等,所以在语句被执行时电脑发现假设不成立,输出结果是「false」。第二句话使用了关系运算符「>=」,表达的意思是「大于等于」,因此电脑要判断 6 是否大于等于6 ,最后发现这个假设是成立的,所以输出结果为「true」。尝试分析一下第三句和第四句话,检查你预测的输出结果和电脑运行的输出结果是否相同。

继续,boolean expression的值叫做「boolean value」,有别于整数、小数、字符串,这是一种独特的数据类型。我们已经知道boolean value的这种数据类型的值只有两种可能性,即「true」以及「false」。上文介绍了如何编写程序让电脑运算一个boolean expression来直接得到一个boolean value,比如电脑运算「6 >= 6」得到的boolean value是「true」。现在我们要了解的是如何在变量里储存这个boolean value,需要用到boolean数据类型的变量。看看这段程序:

		boolean a = true;
		boolean b = 7 > 0;
		System.out.print(a == b);

这段程序定义了两个boolean 类型的变量,a 和 b 。其中,a 被直接赋值为「true」; b 被赋值了布尔式「 7 > 0 」的结果,计算机运行发现 7> 0的假设成立,因此这个布尔式的boolean value是「true」,最终变量 b 被赋值为「true」。随后,在最后一句话,布尔式「a == b」假设变量 a 和 变量 b 里面的数据相同,而电脑运算时发现变量 a 和 b 里面存储的数据都是「true」,因此「a == b」的假设成立,得到输出结果「true」。

U3.2 if Statements and Control Flow 单项选择

我们已经知道如何让计算机对比两个或多个事物。「if statements」的作用是让计算机自己根据对比的结果来选择执行不同的程序语句。最简单的「if statements」包括「if keyword」关键词,「condition」条件,以及「body」语句三个部分。条件必须是一个「boolean value」,只有在条件的值为「true」的时候才运行「body」里面的语句。像这样:

		if (/*这里是条件*/) {
			//大括号中间是body
		}

首先使用「if」关键字表示这段话写的是「if statement」。紧跟着,小括号里应该填写条件。条件必须可以被化简为一个「boolean value」,即要么是「true」要么是「false」。比如,你可以在条件里直接写上「true」或「false」,也可以填写一个的boolean expression。最后是大括号括起来的「body」部分。如果条件的值为「true」,就会运行「body」部分的语句,否则直接跳过这一部分。观察下面的例子:

		double gpa = 2.2;
		if (gpa >= 2.0) {
			System.out.print("哇你真棒,竟然获得了至少50%的分数!");
		}

我们输入了一个变量作为某学生的GPA,赋值为2.2。然后,在if statement的条件中,我们写入了一个boolean expression,这个布尔式假设该学生的GPA至少是2.0。当程序运行时,布尔式访问了变量gpa的数值,得到2.2,然后将2.2和2.0进行对比。电脑此时发现2.2 真的大于等于2.0,假设成立,布尔式的值为「true」。因为「条件condition」的值为「true」,所以「if statement」的body部分将会被执行,例子里具体的表现为输出「哇你真棒,竟然获得了至少50%的分数!」。

尝试这个练习:某公司的人事在筛简历,不要16岁以下的童工。输入一个整数作为年龄,如果不满16岁则输出提示语句「这恐怕不合适吧啊」。

U3.3 if-else Statements 双向选择

在上一小节已经介绍完简单的 if statement,所以你可以使用它进行单向的选择,也就是在满足条件时让程序执行一个特定的行为。但是,如果需要在不满足条件时做出另外一套行为,而不是单纯跳过if statement 里面的语句,就需要进行双向选择。双向选择的 if statement 可以在满足或者不满足条件时分别执行不同的动作。比如,如果GPA大于某个分数,就输出「你被麻省理工录取了」,否则就输出「你没有被麻省理工录取」。

		double gpa = 1.6;//输入GPA
		if (gpa > 2.0) {
			System.out.print("你被麻省理工录取了");
		} else {
			System.out.print("你没有被麻省理工录取了");
		}

观察这段这段程序发现,输入变量gpa的数值是1.6 ,「被麻省理工录取」的条件是GPA大于2.0。也就是说,如果GPA大于2.0就应该输出「你被麻省理工录取了」,如果GPA没有大于2.0就要输出「你没有被麻省理工录取」。这是一个双向选择,条件为「true」和「false」时都分别对应了不同的反应。

if statement的语法规定:双向选择的语句包含两个「body」,也就是两个独立的部分。其中紧随if statement的部分对应「true」的情况,紧随else的部分对应「false」的情况。翻译成中文其实很好理解,「if 如果」「condition is true 条件成立」「执行紧随if statement的部分」「else 否则」「执行紧随 else的部分」。

		if (/* condition */) {
			// 条件成立执行这一部分
		} else {
			// 否则执行这一部分
		}

这样的话,在上面例子的条件下这个学生的GPA是1.6,不满足被麻省理工录取的条件,因此condition为「false」。最终执行else后面的输出语句,得到「你没有被麻省理工录取」的结果。

现在,你已经知道如何使用if statement进行双向选择。尝试在你自己的Eclipse上写作一个程序,用来判断某人是否具有申请老年公交卡的资格:输入一个整数作为年龄,如果已满65周岁则提示允许办理老年公交卡,否则提示too young。

U3.4 else if Statements 多次选择

在有的情况下,前面学到的双向选择仍然不足以解决问题。例如,根据学生卷面分数判断得分等级就需要用到多次选择。多次选择的逻辑是,在一个if statement 语句里面从上到下顺序预设多个条件,然后在运行时按照从上往下的顺序逐个判断。观察下面的写法,我们用一个卷面分数转换得分等级的程序作为例子:

		double score = 62.5;//输入分数
		if (score >= 85) {
			System.out.print("A*");
		} else if (score >= 80) {
			System.out.print("A");
		} else if (score >= 70) {
			System.out.print("B");
		} else if (score >= 60) {
			System.out.print("C");
		} else {
			System.out.print("F");
		}

观察以上例子得出,我们可以在一个「body」的末尾大括号后接上「else if ( ) { } 」来添加一个优先级更低的假设,并且每一种假设都有自己的「body」。按照上一段介绍的的逻辑,这里输入的分数数值为62.5,首先被对比是否大于等于85,得到否定的答案。随后,程序并没有终止,而是把分数的数值继续放在更低优先级的条件里面进行对比。所以电脑还要判断62.5是否大于等于80、70,均得到否定答案。继续,电脑再判断62.5是否大于等于60,终于得到了「true」假设成立的结果,所以执行「score >= 60」这个条件下对应的「body」里面的程序语句,也就是输出「C」作为得分等级,表示62.5分的卷面分数对应C 等级。简单的说,优先级按顺序先后决定,位置越靠上的条件将会被先运算。还要注意的是,如果担心自己手动设计的条件不能覆盖所有可能出现的数据,可以在这个if statement的最后使用单独的「else」来容纳以上已经列出的条件的考虑范围之外的数据。比如,在这个例子中,所有不符合最后一个明确的条件「score >= 60」的数据都会被丢给「else」对应的「body」处理,所以任何小于60的输入数据都会导致输出「F」。

U3.5 Compound Boolean Expression 使用逻辑运算符

你还可以将多个boolean expression使用「logical operators」连接起来。设想这样的应用场景,如果要招募一名员工,要求要么来自QS排名前200的学校,要么大学GPA至少达到3.6。那么,就需要在 if statement 的 condition 里面写出一个 「a 或者 b」格式的假设。「或者」在程序语言里的表达是「 || 」,我们看这个表达式来理解:

		System.out.print(false || false || true);

输出结果是「true」。因为「或者」表达的意思是当多个条件中的任意一个成立时,整个假设就成立。所以就算我用「 || 」连接了无数个boolean value,也只需要出现一个「true」而其他全是「false」就可以让最终的输出值为「true」。

继续,稍微改变一下这个场景。现在要求符合条件的员工必须是来自QS排名前200的学校,并且大学GPA至少达到3.6。这就要求一个boolean expression里面连接的所有 boolean value 都必须为「true」才能让假设成立。用另一种logical operator —— 「 && 」。比如:

		System.out.print(true && true && true);

当所有的假设都成立时,这个 boolean expression的值才最终被输出为「true」。

注意,logical operator的运算顺序是从左往右,一旦已经可以确认结果是「true」或「false」的时候就会停止后面的运算,直接输出结果。这个特性被称为「short-circuited evaluation 」。我们通过具体的例子来理解:

		System.out.print(true && false && true);

上面的语句的输出结果是「false」。已知logical operator 从左往右顺序计算,所以计算机先行判断「true && false」,得到的结果是false。但是,「&&」运算符要求所有的 boolean value 都为「true」的时候最终的结果才为「true」。所以,在第一个运算中得到的「false」就已经排除了最终结果是「true」的可能性,直接输出「false」。

所以,你可以在自己的Eclipse里面尝试一下分别写出这两个程序:

「招募一名员工,输入他的毕业学校QS排名和大学GPA,要求要么来自QS排名前200的学校,要么大学GPA至少达到3.6。输出提示文字提示」

「招募一名员工,输入他的毕业学校QS排名和大学GPA。符合条件的员工必须是来自QS排名前200的学校,并且大学GPA至少达到3.6。输出提示文字提示」

介绍最后一个logical operator,用来得到某个boolean value 的相反值——「 ! 」。这样使用:

		System.out.print( !true );

输出结果是「false」,因为使用了「!」取得「true」的相反值。

U3.6 Equivalent Boolean Expression 等价的布尔式们

boolean expression不仅可以被logical operator连接,还可以使用小括号把一个表达式分为不同的层级。越内层的小括号拥有更高的运算优先级。

比如下面判断两侧布尔式是否相等的这个例子,看左侧的布尔式,括号内的 A && B 会首先被运算。以第一行 A 和 B 都为 True 的情况为例,A && B 的运算结果也为 True,再加上外层的「 ! 」用来取 True 的相反值,最后得到 False。用同样的方法推测一下在表格第二行的情况下,左侧布尔式应该得出什么样的值?对比下面表格中的答案进行检查。

(College Board, 2019)

以第一行为例,左侧boolean expression的值为 false,右侧的boolean expression值也为 false ,两侧最终化简的结果一致,所以两侧的布尔式互为「Equivalent Boolean Expression」。你需要能够化简复杂的boolean expression,并且掌握上面这样的列表法,这是考纲规定内容。上面这样的表格被称作「Truth tables 」,常被用来对比两侧的布尔式能否化简得到相同的值。

U3.7 Comparing Objects

Java语言提供了「equals( ) 」Method来判断两个objects的内容是否相等,这里我们用String object来举例:

		String a = "bio";
		String b = "bio";
		System.out.print(a.equals(b));

这里我们有两个string objects,它们的内容都是「bio」。当我们把 a 使用 dot operator 连接上「equals ( ) 」Method 并且把b 作为参数填入括号时,得到了最后输出语句内的表达式。这个表达式「a.equals(b) 」的含义是「假设 a 等于 b 」,因此,如果 a 和 b 字符串的内容相同即为假设成立,应该给到输出结果「true」。所以你在eclipse里面运行上面这段程序就可以得到 true 的结果。

注意,当objects的类型和内容都相同而只有名称不同的时候,这些除了名称以外一模一样的objects就互为对方的「alias」。比如,a 和 b 在上面的例子中都是String objects,且内容相同,因此我们可以使用「 == 」或者「!= 」来得知它们是否互为「alias」。

		String a = "bio";
		String b = "bio";
		System.out.print(a == b);

输出的结果是「true」,代表 a 和 b 互为aliases。所谓 alias其实是因为reference data type本身的特性而产生的说法,因为reference data type 并不像primitive data type在内存里开辟空间后直接存储数据。reference data type 在内存里开辟空间后存储的是数据的存储位置。也就是说,如果数据 bio 存在盒子001里面,而字符串 a 的属于reference data type,因此在字符串 a 开辟的内存实际上存储的是盒子001的地址,而不是数据bio本身。对于字符串 b 来说,它只需要再开辟一个位置存上盒子001的地址就可以了。我们用下面的图示帮助理解:

总结

所以,你已经知道了如何让电脑判断一个特定的条件是否成立,并且根据特定的条件让程序作出你期望的反应。这部分内容叫做选择结构,它跳脱出原来程序每一句话都要被顺序执行的限制,因此我们可以编程实现的功能就增加了特别多。

练习

  1. 在自己的Eclipse里尝试制作一个卷面分和得分等级的转换工具。在U3.4有简单的例子。
2008-34

3.

2009-2

4.

2009-15

5.

2008-20
by Oscar.L
E-mail [email protected]
No Comments

Send Comment Edit Comment

|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
Previous
Next