建议阅读:3.2-3.6节

决策结构

决策结构是计算机程序中的一种结构,它允许程序做出决策并根据该决策改变其行为。决策是根据逻辑测试的结果做出的。逻辑测试是一种计算,其结果要么为真,要么为假。

If语句

if语句是Java中决策结构的最简单示例。在if语句中进行一个逻辑测试,其值可以为真或假。如果测试结果为真,则执行If分支中的语句。如果测试结果为false,则执行else分支中的语句。一旦执行了适当分支中的语句,执行流程将继续执行if语句后面的语句。

这里有一个简单的例子。下面是计算并输出用户输入的数字的绝对值的程序代码。

公共类AbsValue{公共静态void main(String[] args) {int x, absX;扫描器输入=新的扫描器(System.in);system . out。print(“输入一个整数x: ”);x = input.nextInt();// if语句从if (x < 0)下面开始{//这是if分支absX = -x;} else{//这是else分支absX = x;} system . out。println(“ +x+”的绝对值为“+absX ”);}}

if语句中的测试是一个简单的比较测试,用于检查存储在x中的值是否为正。如果测试结果为true,则执行测试后的代码。如果测试结果为false,则执行else后面的代码。注意,花括号用于分隔两个分支。

花括号的确切位置取决于个人喜好。以下表格均属合法:

if(x < 0) {absX = -x;} else {absX = x;} if(x < 0) {absX = -x;} else {absX = x;}

如果if语句的一个分支的主体减少到只有一条语句,则花括号是可选的。

if(x < 0) abx = -x;else absX = x;

else分支也是可选的。在逻辑只要求在赢博体育特定条件时执行某些操作的情况下,可能只需要if分支。例如,我们可以这样编写上面的程序。

公共类AbsValue2{公共静态void main(String[] args) {int x, absX;扫描器输入=新的扫描器(System.in);system . out。print(“输入一个整数x: ”);x = input.nextInt();absX = x;if (x < 0) abx = -x;system . out。println(“ +x+”的绝对值为“+absX ”);}}

比较测试

接下来我们要看的几个例子都是做数值计算的程序。在数值程序中,大多数决策是在数值比较的基础上做出的。下表显示了Java中可用的比较操作符。

运营商 意义
== 等于
! = 不等于
< 小于
< = 是小于还是等于
> 大于
> = 是大于还是等于

重要警告:注意相等的比较运算符是==,而不是=。这就导致了初级Java程序员常犯的一个错误。下面的代码是合法的,但并没有达到您所期望的效果。

如果(n = 10) n = 0;

在这种情况下,测试中的代码不是测试n是否等于10,而是让n等于10。(之后,不管n的原始值是多少,if分支中的代码都会被执行。)

嵌套if语句

if语句使我们能够提出一个问题,并对这个问题做一些回应。通常,一个特定情况的逻辑会决定我们问多个问题来解决一个情况。在这种情况下,我们可能需要使用嵌套的if。下面的示例演示了它在实践中的工作原理。下面的程序让用户输入构成多项式p(x) = a x2 + b x + c的系数的三个浮点数。然后程序将尝试确定多项式具有哪种根。

必须做出的关键决定是基于判别式的值,b2 - 4ac。如果该量为负,则多项式没有实根。如果它是0,方程有一个实根,如果它大于0,则有两个不同的实根。下面的程序使用一对嵌套的if语句来确定我们正在处理这三种情况中的哪一种。

公共类多项式根{公共静态void main(String[] args){双a, b, c, desc;扫描器输入=新的扫描器(System.in);system . out。print(“输入系数a, b和c: ”);a = input.nextDouble();b = input.nextDouble();c = input.nextDouble();b * b - 4 * a * c;if (desc < 0.0) {System.out。println(“多项式没有实根”);} else {if (desc == 0.0) {System.out。println(“多项式有一个实根”);} else {System.out。println(“多项式有两个实根”);} } } }

第一个if检验区分了没有实根和有实根的情况。在第二种情况下,我们必须问一个进一步的问题,以确定是否有一个重复的实根或两个不同的实根。我们只需将第二个if语句放在第一个if语句的else部分中就可以做到这一点。

链式if - else语句

上面的例子是一个分类任务的例子。我们寻找的答案可以分为三类,所以我们问几个问题来确定我们拥有的是哪一类。注意,为了完成分类,我们必须将询问第二个问题的if语句嵌套在询问第一个问题的if语句的else部分中。

由于整个if - else结构在Java中被认为是单个复合语句,因此我们可以利用特殊规则,即如果if - else语句的if或else部分减少为单个项,则可以消除花括号。部署该规则将代码的结构转换为如下所示:

if (desc < 0.0) System.out。println(“多项式没有实根”);else if (desc == 0.0) System.out。println(“多项式有一个实根”);system . out。println(“多项式有两个实根”);

消除else和if之间的换行,稍微修改一下结构就产生了这种形式。

if (desc < 0.0) System.out。println(“多项式没有实根”);else if (desc == 0.0) System.out。println(“多项式有一个实根”);system . out。println(“多项式有两个实根”);

生成的形式在语法和功能上与我们上面开始使用的嵌套if形式相同。这种所谓的链式if - else形式对于分类非常有用。使用这种形式,我们可以提出一系列问题,以确定哪些类别适用于给定的情况。

下面是原文中的一个例子。java计算身体质量指数,这是一个单独的数字,用于将个人划分为体重过轻或超重。BMI的定义是一个人的体重(公斤)除以身高(米)的平方。下面的程序执行必要的运算,根据用户输入的体重和身高数据计算BMI值。为了使该索引更有意义,该程序还提供了解释。有一个BMI量表可以用来确定一个人是严重体重不足、体重不足、体重正常、超重还是严重超重。该程序使用一个链式if - else结构来确定用户的BMI将他们置于这五个类别中的哪个类别。

公共类ComputeAndInterpretBMI{公共静态void main(String[] args){扫描器输入=新的扫描器(System.in);//提示用户输入以磅为单位的重量。print(“输入重量,单位是磅:”);double weight = input.nextDouble();//提示用户输入高度,单位为英寸System.out。print(“输入高度,单位为英寸:”);double height = input.nextDouble();final double KILOGRAMS_PER_POUND = 0.45359237;//常量final double METERS_PER_INCH = 0.0254;//常量//计算BMI double weightinkg = weight * KILOGRAMS_PER_POUND;double height = * METERS_PER_INCH;double bmi = weightinkg / (hightinmeters * hightinmeters);//显示结果System.out。println("BMI is " + BMI);if (bmi < 18.5) System.out.println("Underweight");else if (bmi < 25) System.out.println("Normal");else if (bmi < 30) System.out.println(“超重”);其他System.out.println(“肥胖”);}}

复合测试

我们想问的一些问题不能简单地用比较来表达。为了使形成更复杂的测试成为可能,Java允许您通过将简单的测试与逻辑操作符组合来形成复合测试。下表显示了可用于组成复合测试的三个逻辑运算符。

运营商 解释
&& 逻辑和
|| 逻辑或
逻辑否定

复合测试是通过组合简单测试以一种相当自然的方式形成的。例如,这里有一个复合测试,用于确定整数变量x是否在5到10(包括5到10)之间。

if((x >= 5)&&(x <= 10))Println (“x落在[5,10]范围内”);

下面是另一个使用复合测试的例子。一年中有些月份有31天,有些月份有30天。下面是一个可以确定一个月有多少天的逻辑示例:

月,日;扫描器输入=新的扫描器(System.in);system . out。print(“输入从1到12的月份:”);month = input.nextInt();if(month == 2) {System.out。println(“假设今年不是闰年…”);天数= 28;} else if(month == 1 || month == 3 || month == 5 || month == 7 || month == 8 || month == 10 || month == 12) {days = 31;} else {days = 30;} system . out。println(“本月将有”+days+" days.");

DeMorgan定律和复合试验

这里有一个设置if测试的比较复杂的问题。假设你在实线上有两个区间[a,b]和[c,d]你必须确定这两个区间是否相交。因为区间可以在实线上的任何位置,所以这两个区间可以有各种相交或不相交的方式:

给定这个相当详尽的可能性列表,我们可以构造一个中等复杂的if - else语句链来捕获赢博体育可能的情况。

对于这个特殊的问题,有一个更简单的替代方法:我们可以试着描述这两个区间不重叠的方式,并构造一个简单的测试。两个区间只有两种不重叠的情况:

构造一个复合测试来检查这两种情况很容易:

if(b < c || d < a){//区间不重叠}else{//区间重叠}

假设现在我们想做一些特殊的事情只在区间重叠的情况下。这将导致我们建立一个类似这样的结构:

if(b < c || d < a) {} else{//做一些重叠的间隔}

这种结构是合法的,但有点笨拙。实际上,在什么都不做的if - else语句中设置if分支是可以的。

一种更好的替代方法是使用逻辑非操作符!来测试 <的否定,间隔不重叠> 。如果我们将上面的测试替换为它的否定,那将允许我们切换If和else情况:

如果(!(b < c || d < a)){//做一些重叠的间隔}else {}

现在我们已经将空分支移到了else分支,我们可以使用“可选的else”规则来删除现在无用的else部分:

如果(!(b < c || d < a)){//做一些重叠的间隔}

我们可以对这个解决方案提出的最后一个抱怨是,测试仍然有点笨拙,因为它有效地表达了双重否定:时间间隔不重叠是不正确的。在这种情况下,我们可以使用两个有用的逻辑转换规则之一,即DeMorgan定律来简化情况。给定两个逻辑命题A和B, demorgan定律允许我们简化涉及否定和它们的逻辑组合的某些表达式:

非(A和B)⇔(非A)或(非B)

非(A或B)⇔(非A)和(非B)

我们可以使用这两种形式中的第二种来简化我们的测试:

!(b

我们可以通过删除否定来进一步简化它:

(!(b = c)&&(d >= a)

最后的测试是确定两个间隔是否重叠的正确测试。

if((b >= c)&&(d >= a)){//做一些重叠的间隔}

直接确定这是适用于重叠间隔的测试是相当困难的。

这个故事的寓意是,如果你不能为某些条件想出一个直接的测试,那就试着为它的否定构建一个测试,然后使用DeMorgan定律之一来简化测试表达式。

优先规则和逻辑组合

算术运算符遵循一组优先规则。例如,乘法运算的优先级高于加法运算。考虑这个表达式

A + b*c

算术运算的优先级规则规定我们应该先做乘法,然后再做加法。如果我们想以不同的顺序执行操作,我们必须使用括号来覆盖优先级规则。表达式

(a + b)*c

明确地说先做加法,然后再做乘法。

优先规则还在构建用于if - else语句的逻辑表达式时发挥作用。逻辑表达式的基本优先规则是

优先级规则告诉我们,比较符周围的括号

(b >= c)&&(d >= a)

都是不必要的。如果我们写

B >= c && d >= a

我们将得到相同的结果,因为比较操作符>=具有比逻辑操作符&&更高的优先级,并且将首先求值,正如我们所希望的那样。

现在我们得到了重叠间隔测试的最终形式:

if(b >= c && d >= a){//做一些重叠的间隔}