南開大學(xué)21級C++作業(yè)常見問題(第3章)
1第三章上機(1)給同學(xué)們布置了兩道題:
設(shè)計算法,求解函數(shù):
要求輸入x,輸出f(x)的值。
設(shè)計算法,判斷整數(shù)為奇數(shù)還是偶數(shù)。
題目主要考察的是選擇算法。滿分示例:
1
2
以上滿分示例皆來自同學(xué)們提交的作業(yè),僅供參考,也未必是最完美的答案,可以有不同的解法。比如說,關(guān)于判斷奇偶性那題,我一直在等待一個完美的解答,但并沒有人在作業(yè)中給出(至少1102班沒有):
其實雖然剛剛講了 if,但是 ?: 才是處理簡單雙路選擇的最簡單的方法。這里程序會判斷x%2的值,如果x為偶數(shù)則x%2為0,則判定為假,輸出“偶”;反之為“奇”。?: 運算符最適合處理這類簡單的雙路選擇。一般來說這些情況可以考慮它:1 有且僅有兩種情況;2 判定方法和執(zhí)行的代碼簡單,可以一句搞定。

各種問題仍然存在:
1?本屬于不同分支的代碼被重復(fù)執(zhí)行
第1題不少錯誤都來自分支設(shè)置的不合理。比如下面這個程序(片段)
如果 x=1,這個程序的執(zhí)行結(jié)果將是“超出范圍”。這是由于前面分支內(nèi)改變了x的值,導(dǎo)致后面又進入了我們不希望進入的分支。改正方法:(1) (推薦)定義一個新變量y來表示函數(shù)值。(2) 改用 else if 保證不會誤執(zhí)行其他分支。
我更加推薦(1)法,用y表示函數(shù)值,我們不缺那點空間;但是如果在分支中直接改變了x值,萬一在復(fù)雜程序中x以后還有用,就會造成不少麻煩。
還存在其他類似的在分支算法中出現(xiàn)的錯誤,這里不再一一列舉了。
2 變量類型
第1題作為連續(xù)函數(shù),x應(yīng)該定義為double;第二題判定整數(shù)的奇偶,則可以直接定義int型。兩個地方都有同學(xué)弄反。變量類型是為實際模型服務(wù)的,需要根據(jù)實際情況決定類型。
3 反復(fù)強調(diào)的語法問題
C++是不認識連續(xù)不等式1<x<2的。很多人都因此出錯。
上機(1)的問題就總結(jié)到這兒。

上機(2)布置了兩道題:
設(shè)計算法,求解
設(shè)計算法,用牛頓法求
在
附近的零點。要求精度為
. 具體流程:
先取
, 進行如下迭代:
直到
,此時
即為所求近似解。
// 該部分講解由譚助教整理。
滿分示例:
1
2
說明:第二題中使用printf并指定輸出精度是不要求掌握的,大家使用cout輸出1.27305也是沒有問題的。精確的答案是1.273049.
附:牛頓法的前幾次迭代結(jié)果為1.3048, 1.27389, 1.273050, 1.273049. 如果你的答案不對,你的錯解是否在這幾個數(shù)字中?想想可能是哪里的問題?

接下來看看都有哪些問題:
1 算法的高效性
關(guān)于階乘求和的題,不少同學(xué)選擇了循環(huán)嵌套,外層負責(zé)求和,內(nèi)層負責(zé)連乘求階乘??梢院颓懊娴臐M分示范對比,差別在哪?

由于階乘存在(x+1)!=(x+1)x!的遞推關(guān)系,我們不需要每次循環(huán)都求一遍 i 的階乘,而只需要把上次循環(huán)的階乘值再 *i 即可。這樣可以用一次循環(huán)完成任務(wù),復(fù)雜度只有O(n),也就是說隨著 n 的增加,計算量只會按線性增加。顯然比循環(huán)嵌套更為高效。
2 庫函數(shù)fabs的調(diào)用
在牛頓法一題中,判斷兩次迭代值之差涉及了絕對值。而C++的cmath庫中就有fabs()函數(shù)可以求絕對值,不少同學(xué)也嘗試了調(diào)用此函數(shù)來表示絕對值。但調(diào)用庫函數(shù)需要先包含相應(yīng)的頭文件:
很多人提交的作業(yè)中用了fabs()函數(shù)卻沒有#include<cmath>。當(dāng)然筆者后來了解到某些版本的Visual Studio里面是可以直接調(diào)用fabs()函數(shù)的,但你不能保證別人的編譯器能夠直接調(diào)用這個函數(shù),所以還是應(yīng)該加上#include<cmath>。
3 牛頓法的循環(huán)條件判斷
幾乎所有的錯誤都來自這一點!我們需要進行的判斷是
判斷上式的正確的表達式應(yīng)該是
錯誤各有不同,不再一一舉例了。