簡體   English   中英

使用二進制搜索在C中查找數字的平方根

[英]Using binary search to find the square root of a number in C

試圖使用二進制搜索計算出數字的平方根,但是我的實現不起作用,我不知道為什么 - 任何幫助表示贊賞,謝謝

繼承我的代碼。 'end'是我希望平方根的數字的值

 while(start <= end) {
   float mid = ((start + end) / 2);
   printf("\nhalving mid");

   if(mid * mid == end){
      sqrt = mid;
      printf("\nsqrt = %d", sqrt);
   }
   if(mid * mid < end){
     start = mid + 1;
     sqrt = mid; 
     printf("\nsqrt: %d", sqrt);
   }
   else{
     start = mid - 1;
   }
 }

除了代碼中的邏輯問題之外,比較浮點數也不是一個好習慣。

mid * mid == end可能總是會失敗,即使對於sqrt(9)也是如此,因為測試浮點數是非常困難的

使用范圍(epsil)而不是比較來查看此實現:

static float my_sqrt(float num)
{
    double start = 0.0;
    double end = num;
    double sqrt = 0.0;
    double epsil = 0.000001;

    while (start <= end)
    {
        double mid = ((start + end) / 2);

        sqrt = mid;
        printf("sqrt = %f\n", sqrt);
        if (fabs(mid * mid -num) <= epsil)
        {
            break;
        }
        else if (mid * mid < num)
        {
            start = mid;
        }
        else
        {
            end = mid;
        }
    }
    return sqrt;
}

我沒有修復你的代碼,只是解釋我將如何寫它。

使用表示解決方案包圍的不變量:

low² <= N < high²

然后取中間值mid ,測試

mid² <= N

允許選擇

low² <= N < mid² and mid² <= N < high²

並縮小搜索間隔。

當搜索間隔很小時,迭代可以停止,因為浮點表示允許(即單個精度為23位)。 你可以在low == high時停止。

建立不變量,

low= 0, high= N

只要0 <= N < N² ,就能做到。 N <= 1時,這不起作用。 快速而骯臟的解決方法是設置high= 1

low= 0
if N >= 1:
    high= N
else:
    high= 1

while low < high:
    mid= 0.5 * (low + high)
    if mid * mid <= N:
        high= mid
    else:
        low= mid

IMO,測試mid² == N ,然后不等式mid² < N會適得其反。 N是完美的正方形時,您可能會認為提前終止可以縮短執行時間。 但實際上,大多數輸入數字都不是完美的正方形,你將進行兩次測試而不是一次,這使得程序平均變慢。

當然最后一行應該是

 end = mid - 1;

符合這三個案例

start..mid-1, mid, mid+1..end

你應該將這個數num要計算平方根和最終end了搜索的時間間隔。


當然,當平方根不是整數時,你也會遇到問題。 然后在某個時刻它將落入其中一個間隔(mid-1, mid)(mid, mid+1) ,因此在算法之外。

因此,您需要將案例分開

[start, mid] (mid, mid+1), [mid+1,end]

如果你想保持整數邊界。 中間案例是

 ( mid*mid> num ) && ( (mid+1)*(mid+1) < num )
public int sqrt(int x) {
    if (x == 0)
        return 0;
    int left = 1, right = Integer.MAX_VALUE;
    while (true) {
        int mid = left + (right - left)/2;
        if (mid > x/mid) {
            right = mid - 1;
        } else {
            if (mid + 1 > x/(mid + 1))
                return mid;
            left = mid + 1;
        }
    }
}

你應該用你的最后一行替換

end = mid -1

在else片段中

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM