决策结构是计算机程序中的一种结构,它允许程序做出决策并根据该决策改变其行为。决策是根据逻辑测试的结果做出的。逻辑测试是一种计算,其结果要么为真,要么为假。
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。下面的示例演示了它在实践中的工作原理。下面的程序让用户输入构成多项式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语句嵌套在询问第一个问题的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.");
这里有一个设置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
最后的测试是确定两个间隔是否重叠的正确测试。
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){//做一些重叠的间隔}