2010-09-05 504 views
1

我想創建一個函數來查找數字的平方根。出於調試目的,它有指示打印當前變量值。函數squareRoot接受兩個參數,xt。然後它宣佈並初始化nsn是加或減的數量,每次使用時減半。 s是什麼被認爲是目前的平方根。運行時,我可以清楚地看到n正在正確調整。但是,前四位數字正確時,s停止更改。我使用的這個呼叫main()C++ double值在乘以時會丟失精度?

cout << squareRoot(1000, 10) << "\n"; 

這應該打印1000平方根最近的十分之一,但有兩個奇怪的事情發生了:

  • 它不會在31.6停止。
  • 它停在4位數!

我的理論,爲什麼它停在四位數是這樣的:在相乘,s失去了一些精度。這是真的?如果是這樣,你能告訴我如何改正它嗎?如果沒有,這是什麼原因造成的,我該如何糾正?

我試圖通過使用另一個變量s1來解決這個問題,這個變量會被乘數和檢查。然後s將與同步增加ns1。這不起作用,所以我回到原來的代碼。

我的代碼如下:

#include <iostream> 
using namespace std; 

double squareRoot(double x, int t) { 
    double s = 0; 
    double n = 0.1; 
    while ((s*s) <= x) { 
      s += n; 
      n *= 2; 
      cout << n << "\n" << s << "\n"; 
    } 
    cout << "\n"; 
    s -= n; 
    // Keep changing until margin of error is reached 
    while ((((s*s) - x) < (1/t)) || ((x - (s*s) < (1/t)))) { 
     // If too high, lower s 
     if ((s*s) <= x) { 
      s += n; 
      n /= 2; 
      cout << "Adding 1/2 of previous n\n"; 
     } 
     // If too low, raise s 
     else if ((s*s) >= x) { 
      s -= n; 
      n /= 2; 
      cout << "Subtracting 1/2 of previous n\n"; 
     } 
     cout << s << "\n" << n << "\n\n"; 
    } 
    return s; 
} 

我運行Windows 7 64位,MSVC++ 2008速成。預先感謝您的所有答案!

+2

您應該查找Newton-Raphson技術來尋找平方根。一旦它接近正確的值(在每次迭代中加倍有效數字的數量),它收斂得非常快。 – 2010-09-05 02:59:41

+0

初始循環非常低效。 – 2010-09-05 03:05:15

+0

強制鏈接:http://docs.sun.com/source/806-3568/ncg_goldberg.html不是因爲內心的微弱,而是因爲它的標題恰到好處。 – 2010-09-05 03:26:28

回答

1

不相關,但是可以通過使用現有的算法(如牛頓法)來加速您的sqrt算法。

它是這樣的:

double mySqrt(double x, unsigned long accuracy = 10) 
{ 
    if(x < 0.0) 
     return(-1.0); 

    double retval = 1.0; 

    for(unsigned long rep = 0; rep < accuracy; rep++) 
     retval = ((x/retval) + retval)/2.0; 

    return(retval); 
} 

牛頓的方法也適用於立方根等 對於小數指數,查找二項式定理。

+0

非常感謝這段代碼,它工作得很好。 – masonsbro 2010-09-05 04:01:28

+0

不客氣。我之前嘗試過,因此我想我可能會與您分享我發現的內容。 – 2010-09-05 04:27:33

+0

Woops。我用「/ 2」而不是「/ 2.0」。現在已經糾正了。並感謝編輯它來編碼的人。 – 2010-09-05 05:26:37

2

它收斂到正確的平方根,但默認情況下,cout僅打印六位有效數字:31.xxxx。

另請注意,您的終止檢查不起作用,因爲對於t> 1,(1/t)將始終評估爲0。改爲使用1./t。

+0

嗯......當試圖解決終止檢查問題時,我的循環永遠不會結束。之前,它結束了。此外,在打印n時,該值是正確的,僅適用於s。 – masonsbro 2010-09-05 03:48:25

+0

我該如何去改變這個默認的六位數字? – masonsbro 2010-09-05 04:04:11

+0

@emasonsbro循環永遠不會結束,因爲它有兩個問題:看到我的答案是另一個。 (當代碼中的兩個錯誤互相補償時,就是這種情況:)) – 2010-09-05 07:47:11

1

原因循環未停止是因爲循環條件不正確。你有

while ((current - target < precision) || (target - current < precision)) { 
    ... 
} 

但無論價值current - target或價值target - current<= 0。和0 < precision。因此你有相當於while (true) {...}循環。
你需要像

while (abs(current - target) > precision) { 
    ... 
} 

(不知道在C獲得絕對值確切功能++)

編輯
只注意到,hamster3null1/t在我面前。

+0

'fabs()'是C中雙精度的絕對值的函數,假設你包含''。當然,這個問題是關於C++的。 – 2010-09-05 03:00:48

+0

@Jonathon - 意思是你應該'#include '而不是。 – Steve314 2010-09-05 03:03:11

+0

@Jonathan謝謝,我糾正了語言和代碼中的另一個錯誤。 – 2010-09-05 03:07:26