標籤:
返回:賀老師課程教學連結 項目要求
【項目1-sin泰勒展式中的錯誤】
下面是sin函數的泰勒展式:
(註:x取弧度值,而非角度值)
編寫了double mysin(double x)用於求sin值,卻“死”在了123°上(122°度的結果已經出來了)。劇透一下,迴圈沒有問題(當然問題會表現在迴圈中)。試著用調試工具找出問題出現在哪裡,然後給出問題的解決方案。
#include<stdio.h>#define pi 3.1415926double mysin(double x);double myabs(double x);int main( ){ double angle; for(angle=0; angle<=180; angle++) printf("sin(%.0f°) = %.3f\n", angle, mysin((angle/180)*pi)); return 0;}//下面定義mysin函數,求sin值double mysin(double x){ double sum=x,x_pow=x,item; int n=1,fact=1, sign=1; //定義變數時賦初值,已經將第一項考慮到累加和sum中 do { fact=fact*(n+1)*(n+2); //fact用於表示階乘,在公式中作分母 x_pow*=x*x; //x_pow是分子中用於表示階乘,在公式中作分母 sign=-sign; //確定即將要累加的這一項的符號 item =x_pow/fact*sign; //計算出要累加的項 sum+=item; //將該項累加上去 n+=2; }while(myabs(item)>1e-5); return sum;}//下面定義myabs函數double myabs(double x){ return ((x>=0)?x:-x);}提示:請進入到mysin中後,注意各變數的變化,看通項是否會收斂,從而使迴圈能夠結束。
[參考解答]
(若需要參考,下面的錦囊逐個找開。你要是將所有錦囊全看了再幹,……老賀會傷心的:每個錦囊裡都有心血,一個一個做出來不容易。)
(若你在實施中,還有意外阻礙了你,請在評論中說明,協助老賀細化錦囊。)
錦囊1:跟蹤要進到mysin函數中,注意用step into。
錦囊2:跟蹤mysin函數的執行,離不了進迴圈,你要是一直用next line(用step into不遇到自訂函數時效果也一樣),點滑鼠很單調,還容易分散注意力。請在迴圈中某語句上設定斷點,用Debug/Continue按鈕“跨越式”跟蹤。
錦囊3:因為問題出在123°,你要是從0°開始跟蹤mysin中的迴圈,我相信你看到這個錦囊時,大概angle不超過10(這已經說明你有足夠的耐心了)。我們需要直接進入到對當角度是123°時對mysin的調用。有兩種方法:
第一種:改一下main函數,例如(還可以有很多方式,只要能直接調用mysin(123°)即可):
int main( ){ double angle; printf(" %.3f\n", mysin((123/180)*pi)); //for(angle=0; angle<=180; angle++) // printf("sin(%.0f°) = %.3f\n", angle, mysin((angle/180)*pi)); return 0;}第二種:在觀察視窗(Watches)中,還可以在跟蹤中改變變數的值,以便看到對應的執行結果。所以如,可以在進入到mysin函數之前,在觀察視窗中加入angle(需要在系統自動出現的變數的下面,自己再輸入變數名),然後在後面直接將想要的值輸入。
其實還可以step into到mysin中後(或者通過斷點直接進入到mysin中後),同樣的辦法修改x的值。
錦囊4:很可能你聽了老賀的指點,用錦囊3中的第一種方法,卻發現進到mysin後,x的值是0,不是123°對應的弧度值。
對不起,我故意挖個坑,你也就進來了。進來了,坐會兒再走。
求123°的sin值,不是調用mysin((123/180)*pi),而是mysin((123.0/180)*pi)!mysin((123/180)*pi)的確就是mysin(0),注意資料類型。
進了這個坑,就要知道,程式的修改,可能會引入新的錯誤。這是軟體工程中的一個規律。
錦囊5:現在進入關鍵時刻(建議還是設好斷點跟蹤),你會發現問題在於,item的絕對值本來是逐漸遞減趨於0的(這體現了泰勒公式的收斂性,實際上,當角度值沒有達到123°時,這種收斂是能保證的),但是,某個時候,item的絕對值卻又大了起來,退出迴圈的希望,逐漸渺茫,以致於失去了希望……你可以觀察fact的值,這裡也發生了一些似乎不可思議的事情。
錦囊到此,現象都有了,下面就需要你的診斷了。請試著解決這個問題。解決了,或者實在想不出來了,再看下面的“真相”。
真相(倒著看,一來你得活動活動身體了,二來,實在不想讓你很容易地放棄自己給出解決方案的探索曆程):
《C語言及程式設計》實踐參考——sin泰勒展式中的錯誤