南开大学21级C++作业常见问题(第3章)
1第三章上机(1)给同学们布置了两道题:
设计算法,求解函数:
要求输入x,输出f(x)的值。
设计算法,判断整数为奇数还是偶数。
题目主要考察的是选择算法。满分示例:
1
2
以上满分示例皆来自同学们提交的作业,仅供参考,也未必是最完美的答案,可以有不同的解法。比如说,关于判断奇偶性那题,我一直在等待一个完美的解答,但并没有人在作业中给出(至少1102班没有):
其实虽然刚刚讲了 if,但是 ?: 才是处理简单双路选择的最简单的方法。这里程序会判断x%2的值,如果x为偶数则x%2为0,则判定为假,输出“偶”;反之为“奇”。?: 运算符最适合处理这类简单的双路选择。一般来说这些情况可以考虑它:1 有且仅有两种情况;2 判定方法和执行的代码简单,可以一句搞定。

各种问题仍然存在:
1 本属于不同分支的代码被重复执行
第1题不少错误都来自分支设置的不合理。比如下面这个程序(片段)
如果 x=1,这个程序的执行结果将是“超出范围”。这是由于前面分支内改变了x的值,导致后面又进入了我们不希望进入的分支。改正方法:(1) (推荐)定义一个新变量y来表示函数值。(2) 改用 else if 保证不会误执行其他分支。
我更加推荐(1)法,用y表示函数值,我们不缺那点空间;但是如果在分支中直接改变了x值,万一在复杂程序中x以后还有用,就会造成不少麻烦。
还存在其他类似的在分支算法中出现的错误,这里不再一一列举了。
2 变量类型
第1题作为连续函数,x应该定义为double;第二题判定整数的奇偶,则可以直接定义int型。两个地方都有同学弄反。变量类型是为实际模型服务的,需要根据实际情况决定类型。
3 反复强调的语法问题
C++是不认识连续不等式1<x<2的。很多人都因此出错。
上机(1)的问题就总结到这儿。

上机(2)布置了两道题:
设计算法,求解
设计算法,用牛顿法求
在
附近的零点。要求精度为
. 具体流程:
先取
, 进行如下迭代:
直到
,此时
即为所求近似解。
// 该部分讲解由谭助教整理。
满分示例:
1
2
说明:第二题中使用printf并指定输出精度是不要求掌握的,大家使用cout输出1.27305也是没有问题的。精确的答案是1.273049.
附:牛顿法的前几次迭代结果为1.3048, 1.27389, 1.273050, 1.273049. 如果你的答案不对,你的错解是否在这几个数字中?想想可能是哪里的问题?

接下来看看都有哪些问题:
1 算法的高效性
关于阶乘求和的题,不少同学选择了循环嵌套,外层负责求和,内层负责连乘求阶乘。可以和前面的满分示范对比,差别在哪?

由于阶乘存在(x+1)!=(x+1)x!的递推关系,我们不需要每次循环都求一遍 i 的阶乘,而只需要把上次循环的阶乘值再 *i 即可。这样可以用一次循环完成任务,复杂度只有O(n),也就是说随着 n 的增加,计算量只会按线性增加。显然比循环嵌套更为高效。
2 库函数fabs的调用
在牛顿法一题中,判断两次迭代值之差涉及了绝对值。而C++的cmath库中就有fabs()函数可以求绝对值,不少同学也尝试了调用此函数来表示绝对值。但调用库函数需要先包含相应的头文件:
很多人提交的作业中用了fabs()函数却没有#include<cmath>。当然笔者后来了解到某些版本的Visual Studio里面是可以直接调用fabs()函数的,但你不能保证别人的编译器能够直接调用这个函数,所以还是应该加上#include<cmath>。
3 牛顿法的循环条件判断
几乎所有的错误都来自这一点!我们需要进行的判断是
判断上式的正确的表达式应该是
错误各有不同,不再一一举例了。