2016-11-19 81 views
1

由於某種原因,我的平方根程序得到的答案與大多數輸入所得到的答案略有不同。我不確定這是爲什麼。只有某些輸入是錯誤的。在給出答案之後,我也會在最後得到一個分段錯誤,但我不確定這是爲什麼。C++遞歸平方根

#include<iostream> 
#include<cmath> 
#include<cfloat> 
#include<string> 
#include <cstdlib> 
using namespace std; 

//declare sqroot function calls recursive function newton 
double sqroot1(double num); 
double newton(double num, double guess); 
int main(int argc, char **argv) 
{ 

    for(int i = 0 ; i < argc ; i++) 
    { 
     cout<<"sqroot("<<argv[i+1]<<") is "<< sqroot1(atoi(argv[i+1]))  <<endl; 
    } 
} 

double newton(double num, double a) 
{ 
    if ((abs(a*a - num) <= FLT_EPSILON)) 
    { 
     return a; 
    } 
    else 
    { 
     newton(num, (a+num/a)/2); 
    } 
} 

double sqroot1(double num) 
{ 
    double sqrt = newton(num,num/2); 
    return sqrt; 
} 
+0

啓用所有警告並查看編譯器告訴您什麼。然後看[爲什麼使用命名空間標準被認爲是不好的練習?](http://stackoverflow.com/q/1452721/995714) –

+0

什麼是一些值不好的平方根,你得到什麼值? – 1201ProgramAlarm

回答

2

的功能未定義的行爲,因爲你忘了把return語句

double newton(double num, double a) 
{ 


    if ((abs(a*a - num) <= FLT_EPSILON)) 
    { 
     return a; 
    } 
    else 
    { 
     newton(num, (a+num/a)/2); 
     ^^^^^^^^^^^^^^^^^^^^^^^^^^^ 
    } 


} 

必須有

return newton(num, (a+num/a)/2); 
1

你得到的崩潰,因爲您嘗試訪問argv[argc],這已經超過了argv陣列的末尾。

您的號碼很有可能是因爲您正在與FLT_EPSILON比較,這是float的值。 DBL_EPSILON用於雙打。不過,與這兩者中的任何一個比較都不是這個問題的正確方法。您需要檢查相對於您的a值的比例差異。

0

我看應該首先固定兩個基本錯誤:

  1. 你的主要功能沒有回報。您應該在最後的}之前將return 0;放在主要功能的末尾。您正嘗試訪問不存在的argv[argc]。該陣列中最後一個存在的元素是argv[argc - 1]。嘗試更改循環語句,以便它不嘗試讀取數組中不存在的部分。

0

添加到1201ProgramAlarm的答案,爲什麼以下這麼糟糕?

if ((abs(a*a - num) <= eps)) 

比方說eps是1e-15,比DBL_EPSILON大一點。那麼,如果a甚至是中等大(類似於5或更大),那麼a*a的最後一位(ulp)中的單位大於eps,且條件只有在a*a == num時才爲真。有一個風險,四捨五入,這將不會達到,你最終無限遞歸和崩潰。

現在,讓我們說,num非常小,使得對於初始猜測

abs(num/2*num/2 - num) <= eps 

因此,舉例來說,sqroot1(1E-20)將評估

abs(1e-40/4 - 1e-20) <= 1e-15 

這是真實的,你會得到5e-21作爲1e-20的平方根。這是非常精確的。