2017-02-16 84 views
1

所以我把它作爲一項家庭作業。我明白有很多方法可以讓代碼更加高效和準確,但這是我的教授想要完成的方式。C++找到沒有sqrt函數循環毛刺的平方根

我有循環問題。當我問67的平方根時,它確實找到了它,但它循環了3次正確的答案。

Enter a value to be square rooted: 
67 
33.5 
guess = 17.75 
guess = 10.7623 
guess = 8.49387 
guess = 8.19096 
guess = 8.18535 
guess = 8.18535 
guess = 8.18535 
The program took 7 guess to find an estimation. 

當我試圖找到的5平方根它發現它,但會繼續無限循環

using namespace std; 

int main() 
{ 
double guess2; 
double squarenumber; 
double guess1; 
int numofguess = 0; 

cout << "Enter a value to be square rooted: " << endl; 
cin >> squarenumber; 
guess1 = squarenumber/2; 
cout << guess1 << endl; 

do 
{ 

guess2 = (guess1 - (((guess1 * guess1) - squarenumber)/(2* guess1))); 
guess1 = guess2; 

cout << "guess = " << guess2 << endl; 

numofguess = numofguess + 1; 

} while ((guess2 * guess2) > squarenumber); 

cout<< "The program took "<< numofguess <<" guess to find an estimation."; 

return 0; 
} 
+5

,而在調試器中逐行執行代碼? –

+1

嘗試每次通過循環打印'guess2 * guess2'。確保用大量的精確數字打印。 – Barmar

+3

雙精度數據包含6位以上的十進制數字,因此可能不會顯示數字的差異。檢查這篇文章[浮點數學破碎?](http://stackoverflow.com/questions/588004/is-floating-point-math-broken) –

回答

1

我認爲你缺少的是一個適當的退出條件。 你的代碼被寫成無限循環直到猜測是「完美」的。 如果當前猜測與之前的猜測相同,您應該有退出條件檢查,這顯然意味着您不會做得更好。 這是基於你的代碼我的建議:

using namespace std; 

int main() 
{ 
double guess2; 
double squarenumber; 
double guess1; 
int numofguess = 0; 

cout << "Enter a value to be square rooted: " << endl; 
cin >> squarenumber; 
guess2 = guess1 = squarenumber/2; 
cout << guess1 << endl; 

const double epsilon = squarenumber * 1E-6; 
do 
{ 
guess1 = guess2; 
guess2 = (guess1 - (((guess1 * guess1) - squarenumber)/(2* guess1))); 


cout << "guess = " << guess2 << endl; 

numofguess = numofguess + 1; 

} while ((guess2 * guess2) > squarenumber && fabs(guess2-guess1) > epsilon); 

cout<< "The program took "<< numofguess <<" guess to find an estimation."; 

return 0; 
} 
+0

這不會工作明顯,因爲在'guess1 = guess2;'行後,'fabs(guess2-guess1)'總是爲零 – user31264

+0

你是對的...我編輯了代碼來修復這個愚蠢的錯誤。 –

+0

我會使用'if(fabs(...)εbreak;'或將'guess1 = guess2'移動到循環的開頭,所以你不需要另一個變量 – user31264

0

的MickaëlC.吉馬良斯的回答是基本正確,檢查一個episolon值(從正確的答案和你的答案絕對差)。但是「(guess2 * guess2)> squarenumber」應該完全放棄。這是因爲這個價值在理論上可能會超調並且太低。如果值太低,算法實際上會向上。例如如果你想SQRT(25)和你的「guess1」的預測是在方式2過低,則guess2就等於

(2 - (((2 * 2) - 25)/(2* 2))) = 7.25; 

,並在下次迭代,然後下降到6.725624,因此,在正確的方向頭。低值實際上得到提升並最終接近目標。通過停止,如果價值下降到真正的SQRT以下,那麼你可能會得到「誤報」,太低的價值被接受爲足夠準確。

系統「卡住」的時間基本上像故事Acchiles和烏龜。在每一步中,系統將剩餘的距離除以某個數值,但因此每一步的變化都較小,理論上可能不會收斂於確切的值,因此您可以決定要達到多少準確度,以便它完成設定時間。

此外,系統似乎需要太多步驟來收斂的問題是因爲浮點數的存儲精度更高,但cout的顯示精度有限。您可以控制通過發送設定值的打印命令之前,清點:

std::cout << std::fixed; // force all values to show to the same decimals 
std::cout << std::setprecision(6); // set how many places to show 

這些代碼可以流在一個命令來清點前值打印以及:那你觀察

std::cout << std::fixed << std::setprecision(6) << "guess = " << guess2 << endl;