二进制搜索平方根[作业]

时间:2014-12-07 15:05:47

标签: java binary-search invariants loop-invariant

对于赋值,我必须使用二进制搜索创建一个方法来查找整数的平方根,如果它不是一个平方数,它应该返回一个整数s,使s * s <=数字(所以对于15它将返回3)。我到目前为止的代码是

public class BinarySearch {

    /**
     * Integer square root Calculates the integer part of the square root of n,
     * i.e. integer s such that s*s <= n and (s+1)*(s+1) > n
     * requires n >= 0
     *
     * @param n number to find the square root of
     * @return integer part of its square root
     */
    private static int iSqrt(int n) {
        int l = 0;
        int r = n;
        int m = ((l + r + 1) / 2);

        // loop invariant
        while (Math.abs(m * m - n) > 0) {
            if ((m) * (m) > n) {
                r = m;
                m = ((l + r + 1) / 2);
            } else {
                l = m;
                m = ((l + r + 1) / 2);
            }
        }
        return m;
    }

    public static void main(String[] args) {
        //gets stuck
        System.out.println(iSqrt(15));
        //calculates correctly
        System.out.println(iSqrt(16));
    }
}

这会返回正确数字的正确数字,但会在其他整数的无限循环中停留。我知道问题在于while条件,但由于数字变得越大,方形数字之间的差距变得越大,我无法确定要放什么(所以我不能把它放在那里差距必须低于阈值)。这项练习是关于不变量的,如果它有帮助的话(因此它以这种方式设置)。谢谢。

4 个答案:

答案 0 :(得分:0)

考虑一下:Math.abs(m*m-n) > 0总是非正方形数字,因为它永远不为零,.abs不能为负数。这是你的循环条件,这就是循环永不结束的原因。

这能为您提供足够的信息让您前进吗?

答案 1 :(得分:0)

您需要更改while (Math.abs(m * m - n) > 0)以允许误差范围,而不是要求它现在正好等于零。

尝试while((m+1)*(m+1) <= n || n < m * m)

答案 2 :(得分:0)

#define EPSILON 0.0000001
double msqrt(double n){
    assert(n >= 0);
    if(n == 0 || n == 1){
       return n;
     }
    double low = 1, high = n; 
    double mid = (low+high)/2.0;
    while(abs(mid*mid - n) > EPSILON){
       mid = (low+high)/2.0;
       if(mid*mid < n){
          low = mid+1;
       }else{
          high = mid-1;
       }
     }
return mid;}

如上所示,您应该简单地应用二分搜索(二分法) 并且您可以最小化Epsilon以获得更准确的结果,但运行需要更多时间。 编辑:我用c ++编写代码(对不起)

答案 3 :(得分:-1)

正如Ken Bloom所说,你必须要有一个错误,1。我已经测试了这个代码,它的运行符合预期的15个。你还需要使用float,我认为这个算法不可能用于int(虽然我没有数学证明)

private static int iSqrt(int n){
float l = 0;
float r = n;
float m = ((l + r)/2);


while (Math.abs(m*m-n) > 0.1) {
    if ((m)*(m) > n) {
        r=m;
        System.out.println("r becomes: "+r);


    } else {
        l = m;
        System.out.println("l becomes: "+l);

    }
    m = ((l + r)/2);
    System.out.println("m becomes: "+m);
}

return (int)m;

}