2016-09-27 288 views
0
#include <stdio.h> 
#include <stdlib.h> 

int main(int argc, char **argv) { 

if (argc != 2) { 
    printf("Too many arguments.\n", argc); 
return 1; 
} 

double n; 
n = atof(argv[1]); 

if (n<0) { 
    printf("Negative argument.\n"); 
return 1; 
} 

double r; 
r = n; 
int iteration; 
iteration = 0; 

while(calcError(n,r)<1e-6) { 
    iteration = iteration +1; 
    r = (r + n/r)/2; 
    printf(" %d. sqrt(%f)~= %f,error=%e\n",iteration,n,r,calcError(r,n)); 
} 

printf("sqrt(%f)=%f to six places\n",n,r); 

return 0; 
} 

int calcError (double n, double r) { 

double delta; 

delta = n-r*r; 
delta = delta > 0 ? delta : -delta; 

return 0; 

} 

運行此代碼會生成一個無限循環。我還得到一個警告:格式'%e'需要類型'double'的參數,但參數5的類型爲'int'[-Wformat]。爲什麼是這樣?爲什麼我的while循環無限?

回答

4

calcError總是返回0,所以

while(calcError(n,r)<1e-6) 

一樣好,因爲

while(0 < 1e-6) 

while(true) 

至於警告,編譯器說,究竟出了什麼問題:calcError回報一個int,但您提供的格式字符串(%e)需要double。這將產生未定義的行爲。如下更改返回類型將解決此問題。

看着你的代碼,我想你想循環,只要錯誤大於1e-6。如果這是正確的,你可能需要修改你的calcError是如下:

int calcError (double n, double r) 
{ 
    double delta; 

    delta = n-r*r; 
    delta = delta > 0 ? delta : -delta; 
    return delta; 
} 

可縮短至

double calcError(double n, double r) 
{ 
    return fabs(n-r*r); 
} 

,改變你的循環條件循環,直到它的體積更小:

while(calcError(n,r) > 1e-6) 
+0

謝謝,這是有道理的。但是,使用該更改運行代碼仍會生成相同的警告。不再有無限的while循環,它現在完全繞過while循環,並顯示:sqrt(24.000000)= 24.000000到六個地方 – normystar

+1

我認爲只要誤差大於你的epsilon就想循環,所以使用這個:'while(calcError(n,r)> 1e-6)' – krzaq

+0

我很確定[this](http://melpon.org/wandbox/permlink/Oqw54hodZugBWEnn)正是你想要的。順便說一句,請注意,對'printf'調用'calcError'具有相反的順序。 – krzaq

0

在你calcError()功能,你有,

return 0; 

因此在您的表達中,calcError()將始終爲零。

(0 < 1e-6)總是如此。

0

你有while(calcError(n,r)<1e-6)calcError總是返回0,所以當然你的循環將永遠持續下去。我想你的意思是讓calcError返回delta而不是0