7.9 练习
本章的示例代码位于仓库 ThinkJavaCode 的目录 ch07 中,有关如何下载这个仓库,请参阅前言中的“使用示例代码”一节。做以下的练习前,建议你先编译并运行本章的示例。
如果你还没有阅读 A.5 节,那么现在正是阅读的好时机。该节介绍了 Checkstyle——一款分析源代码众多方面的工具。
练习7-1
请看下面的方法,并思考问题:
public static void main(String[] args) {loop(10);}public static void loop(int n) {int i = n;while (i > 1) {System.out.println(i);if (i % 2 == 0) {i = i / 2;} else {i = i + 1;}}}
(1) 绘制一个表格,用来显示变量 i 和 n 在循环期间的值。在这个表格中,每次迭代要占据一行,每列对应一个变量。
(2) 这个程序的输出是什么?
(3) 只要 n 的值为正,这个循环就终将结束。你能证明这一点吗?
练习7-2
给定数字 a,要求你计算它的平方根。一种解决方案是先粗略地猜测结果 x0,再用下面的公式提高结果的精度:

例如,要计算 9 的平方根,可从 x0=6 开始,再用前面的公式计算 x1=(6+9/6)/2 = 3.75,这更接近于准确的结果。我们可重复这个过程,根据 x1 计算 x2,再依次类推。就此例而言,x2=3.075,x3=3.00091。这种计算的速度非常快,很快就能找到正确的答案。
请编写一个名为 squareRoot 的方法,让它接受一个 double 值,并用前面的技巧计算其平方根的近似值。可不能用 Math.sqrt 哟!
为计算初始结果,可使用公式 a/2。这个方法应该不断迭代,直到两个相邻近似结果的差小于 0.0001。可用 Math.abs 计算差的绝对值。
练习7-3
在练习 6-9 中,你编写了一个以迭代方式计算幂的方法,它接受 double 值 x 和整数值 n,并返回 xn。现在请编写一个迭代方法来执行这种计算。
练习7-4
6.7 节中介绍了一个计算阶乘的递归方法,请编写方法 factorial 的迭代版本。
练习7-5
要想计算 ex 的值,一种办法是使用如下的无穷级数展开:

在上述级数中,第 i 项为“xi/i !”。
(1) 编写一个名为 myexp 的方法,它接受形参 x 和 n,并将上述级数的前 n 项相加来计算 ex 的近似值。为计算阶乘,可使用 6.7 节中的方法 factorial,也可使用前一个练习中编写的迭代版本。
(2) 在上述级数中,每一项的分子都是前一项的分子乘以 x,而每一项的分母都是前一项的分母乘以 i。利用这一点可避免使用方法 Math.pow 和 factorial,从而提高这个方法的效率。请按这种方式修改你在第 1 步编写的方法,并确定得到的结果相同。
(3) 编写一个名为 check 的方法,它接受形参 x,并显示 x、myexp(x) 和 Math.exp(x) 的值,其输出类似于下面这样:
1.0 2.708333333333333 2.718281828459045
要想用制表符分隔各列的值,可使用转义序列 "\t"。
(4) 修改级数包含的项数(check 向 myexp 传递的第二个实参),并查看这种修改对结果准确度的影响。在 x 为 1 的情况下调整值,直到估算值与正确的结果相同为止。
(5) 在方法 main 中编写一个循环,依次用实参值 0.1、1.0、10.0 和 100.0 调用 check。随着 x 值不断变化,结果的准确度将如何变化?比较估算值和实际值有多少位相同。
(6) 在方法 main 中编写一个循环,依次用实参值 - 0.1、- 1.0、- 10.0 和 - 100.0 调用 check,看看准确度将如何变化。
练习7-6
要想计算 exp(-x2) 的值,一种办法是用如下的无穷级数展开:

在上述级数中,第 i 项为“(-1)ix2i/i !”。请编写一个名为 gauss 的方法,它接受形参 x 和 n,并返回上述级数中前 n 项的和。编写这个方法时,可不能使用方法 factorial 和 pow 哟!
