二级计算机选择题必考(计算机等级二级考试辅导)(1)

1、应用递归算法编程实现某个正整数的阶乘

(1)什么是阶乘(Factorial)及阶乘的计算方法

阶乘是基斯顿·卡曼(Christian Kramp,1760~1826)于 1808 年发明的运算符号,是数学术语。一个正整数的阶乘是所有小于及等于该数的正整数的积,并且0的阶乘为1。自然数N的阶乘写作N!。

对于阶乘的计算方法和如何表示某个数的阶乘,读者在高中数学中都应该学习过。作者在此不再重复,但读者要注意的是,在阶乘的定义中特别说明0的阶乘为1。另外,在阶乘的定义中的n为正整数,不应该为负整数。

(2)阶乘的应用

阶乘在数学中通常用于组合和排列中,比如一个班级中有30个人排队,那么就有30!种排列方式。

(3)问题分析和解题思路

本问题的关键是如何在Java程序中实现递归算法,而所谓的递归算法,其实就是程序的自身调用。递归算法的最大意义在于它能把一个复杂的问题层层转换为一个比较小的但和原问题相似的问题来求解,从而简化对原始负责问题的求解。但读者在应用递归算法时一定要明确它适合具有如下特点的问题:首先,该问题可被分解为若干层简单的子问题;其次,子问题和其上层问题的解决方案是一致的;最后,外层问题的解决是依赖于其子问题的解决。

在本问题的实现程序中,首先获得用户从键盘中输入的一个数字变量,然后再计算该数的阶乘,最后打印出计算的结果。下面给出具体的示例程序。

(4)在MyEclipse开发工具中创建出一个类名称为NumberFactorial,程序包名称为com.bluedream.javaoop,并且包含有main()方法的Java程序类,NumberFactorial程序类的创建过程参看如下示例图所示。

二级计算机选择题必考(计算机等级二级考试辅导)(2)

(5)点击对话框中的“Finish”按钮,MyEclipse开发工具将帮助开发人员创建出NumberFactorial类的初始程序,在NumberFactorial类的初始程序中只包含有默认构造方法和main()方法。最终的程序结果示例参看如下示图所示。

二级计算机选择题必考(计算机等级二级考试辅导)(3)

(6)在NumberFactorial程序类中设计一个名称为getFactorialResult的方法

该方法实现阶乘的递归算法,接收用户从键盘输入的一个数字变量,然后计算该数的阶乘并将计算的结果返送给上层的调用者程序。getFactorialResult的方法的功能实现的程序代码参看如下示例图所示。

二级计算机选择题必考(计算机等级二级考试辅导)(4)

读者在应用递归算法时一定要注意其“出口”,也就是递归循环结束的条件(注意getFactorialResult的方法体内的条件语句),否则递归循环将会是“死循环”;此外,为了能够在getFactorialResult的方法体内以及在main()方法中都能够方便地实现对getFactorialResult方法的再次调用,在现阶段的程序实现中,暂时将getFactorialResult方法设计为静态(static)方法。

在Java语言的语法定义中,用static修饰的方法称为静态方法(也称类方法)。由于static类型的方法是属于整个类所有而非属于某个特定的对象所有,因此对static类型的方法调用是直接通过类名调用,而不需要实例化对象。

(7)编程NumberFactorial程序类中的main()方法

在main()方法中主要是获得用户从键盘输入的数字,并将该数字传给getFactorialResult方法以计算出该数字的阶乘结果。但由于getFactorialResult方法设计为静态方法,因此在main()方法中不需要通过对象实例调用它,而是直接调用getFactorialResult方法。main()方法的最终的程序代码参看如下示例图所示。

二级计算机选择题必考(计算机等级二级考试辅导)(5)

在前面的示例程序中由于将计算阶乘的功能方法getFactorialResult设计为静态方法,因此在main()方法中采用NumberFactorial.getFactorialResult(someOneUserInputNumber);的方式调用此静态方法(采用类名称限定)。但由于在Java应用程序中的main()方法本身也是static静态方法,因此在程序代码中的如下语句:

int someNumberFactorialResult =NumberFactorial.getFactorialResult(someOneUserInputNumber);

其实也可以简写为如下的代码:

int someNumberFactorialResult = getFactorialResult(someOneUserInputNumber);

因为静态方法可以直接调用同类中的静态成员,但不能直接调用非静态成员。从严谨的面向对象编程的设计要求的角度,对static静态方法应该要采用类名限定的方式进行调用。

(8)执行NumberFactorial程序类示例代码

在MyEclipse开发工具中右击源程序,在弹出的快捷菜单中选择“Run as”下拉菜单中的“Java Application”子菜单项目以在Java虚拟机环境中执行示例,将执行本示例NumberFactorial类程序。参看如下示例图所示。

二级计算机选择题必考(计算机等级二级考试辅导)(6)

作者在显示的控制台中输入数字4,将显示出该数据的阶乘计算结果,参看如下示例图所示。

二级计算机选择题必考(计算机等级二级考试辅导)(7)

作者再在显示的控制台中输入数字11,将显示出该数据的阶乘计算结果,参看如下示例图所示。

二级计算机选择题必考(计算机等级二级考试辅导)(8)

2、将示例程序中的静态方法改变为类中的方法以体现面向对象程序设计中的封装特性

(1)少用static静态方法,尽可能应用对象实例方法

Java程序中的静态方法在被调用时可以不用创建类的实例对象并通过实例对象调用该方法,而是在static静态方法中直接可以调用它或者在非static静态方法中采用类名称限定的方式进行调用。因为static静态方法属于整个类的(类中的全局方法),不用创建任何对象实例也可以直接调用它。

读者需要注意的是,在Java程序中的静态方法定义中,需要在方法声明时在方法名称前面要加static 修饰符——参看如下代码示例。

public static int getFactorialResult(int someOneUserInputNumber) { }

但为了更好体现面向对象程序设计中的“封装”设计思想,少用类中的全局方法而改用实例方法。为此,将本示例程序中的getFactorialResult方法设计为实例方法,在该方法的定义声明中除掉方法名称前面的static 修饰符。

(2)优化后的程序示例代码

由于getFactorialResult方法不再是static静态方法,在main()方法中调用getFactorialResult方法方法则需要通过对象实例进行调用。为此在main()方法中需要创建出NumberFactorial类的对象实例,下面为优化后的程序代码示例。

二级计算机选择题必考(计算机等级二级考试辅导)(9)

(3)执行优化后的程序示例

作者在显示的控制台中仍然输入数字4,将显示出该数据的阶乘计算结果,参看如下示例图所示,与未优化前的程序执行的结果相同。

二级计算机选择题必考(计算机等级二级考试辅导)(10)

作者继续再在显示的控制台中输入数字11,将显示出该数据的阶乘计算结果,参看如下示例图所示,与未优化前的程序执行的结果相同。

二级计算机选择题必考(计算机等级二级考试辅导)(11)

3、再次优化本示例程序代码以提高程序的正确性

(1)目前的示例程序所存在的不足之处——无法识别输入的数字是否是合法的数字

根据前面的阶乘的定义,在阶乘的定义中的n为正整数,不应该为负整数。但Scanner(System.in).nextInt()只能保证获得整数,而不能保证只能获得正整数。因此,当用户输入如下的负数(比如 -4)时,程序可能会出现计算错误,参看如下示例图所示。

二级计算机选择题必考(计算机等级二级考试辅导)(12)

而将所输入的数据改变为-11,也仍然出现错误,参看如下示例图所示。

二级计算机选择题必考(计算机等级二级考试辅导)(13)

(2)问题分析和解题思路

为此,需要在main方法中增加对用户所输入的数据进行合法性判断的条件语句,如果用户输入的数据值是负数,则直接提示输入数据错误,需要重新输入正整数。修改后的main()方法的程序代码参看如下示例图所示。

二级计算机选择题必考(计算机等级二级考试辅导)(14)

(3)再次执行优化后的程序示例

在MyEclipse开发工具中右击源程序,在弹出的快捷菜单中选择“Run as”下拉菜单中的“Java Application”子菜单项目,以在Java虚拟机环境中执行本示例NumberFactorial类程序。参看如下示例图所示。

作者首先输入合法的数字,比如11,程序执行的结果参看如下示例图所示。

二级计算机选择题必考(计算机等级二级考试辅导)(15)

作者再输入不合法的数字,比如-11,程序执行的结果参看如下示例图所示——此时将提示出错误信息,并要求重新输入数字。

二级计算机选择题必考(计算机等级二级考试辅导)(16)

4、进一步优化示例程序代码以提高程序的健壮性和可靠性

(1)目前示例程序所存在的不足

对于正整数的阶乘中的数字N在理论上可以是任意的正整数,比如N可能是一个很大的正整数。而在程序代码中获得用户的键盘输入的数据值定义为Java语言中的int数据类型,它有一定的数据范围。

因此,当待计算阶乘中的数字N比较大时,数字N的阶乘的计算结果也将会很大,甚至为一个天文数值!从而超出了Java语言中的int数据类型的有效定义范围。如下示图中所示31的阶乘的计算结果为:738197504

二级计算机选择题必考(计算机等级二级考试辅导)(17)

但32的阶乘应该等于31的阶乘的计算结果*32,也就是738197504*32。但程序的计算结果如下(已经超出int数据类型的有效定义范围,从而产生数据溢出)

二级计算机选择题必考(计算机等级二级考试辅导)(18)

而对于34的阶乘的计算结果,本示例程序报告的结果为0(参考下面的示图)。因此程序出现了错误,需要进一步完善程序代码以提高程序的健壮性和可靠性——将示例程序中的int数据类型改变为long类型,当然相关的程序代码也需要对应地进行修改。

二级计算机选择题必考(计算机等级二级考试辅导)(19)

(2)优化后的getFactorialResult方法的程序代码示例,读者注意其中的数据类型由int转变为long类型,参看如下示例图所示。

二级计算机选择题必考(计算机等级二级考试辅导)(20)

(3)优化后的main()方法的程序代码示例,读者注意其中的数据类型由int转变为long类型,参看如下示例图所示。

二级计算机选择题必考(计算机等级二级考试辅导)(21)

(4)再次执行优化后的程序示例

在MyEclipse开发工具中右击源程序,在弹出的快捷菜单中选择“Run as”下拉菜单中的“Java Application”子菜单项目,以在Java虚拟机环境中执行本示例NumberFactorial类程序。

作者在显示的控制台中输入数字34,将能够正确地返回34阶乘的计算结果,参看如下示例图所示。

二级计算机选择题必考(计算机等级二级考试辅导)(22)

作者再在显示的控制台中输入数字100,测试程序是否能够正确地返回100阶乘的计算结果,参看如下示例图所示。

二级计算机选择题必考(计算机等级二级考试辅导)(23)

但程序出现了错误,说明尽管将数据类型声明为long,但对于计算比较大的数字的阶乘时仍然可能会超出该数据类型的有效定义范围。为此,只能继续再定义为更大的数据定义范围的数据类型。

但毕竟计算机数据处理的数据是有限数位的,因此对于计算某个数的阶乘等问题时,必须要根据问题的应用场景合理地限定数据的范围。数据可能会是无限的,但机器是有限的!

计算机等级二级考试辅导:综合应用上机模拟题及解答(第5部分)

计算机等级二级考试辅导:综合应用上机模拟题及解答(第4部分)

计算机等级二级考试辅导:综合应用上机模拟题及解答(第3部分)

计算机等级二级考试辅导:综合应用上机模拟题及解答(第1部分)

计算机等级二级考试辅导:综合应用上机模拟题及解答(第2部分)

,