Java 平方根的二进制搜索[家庭作业]

Java 平方根的二进制搜索[家庭作业],java,binary-search,invariants,loop-invariant,Java,Binary Search,Invariants,Loop Invariant,对于赋值,我必须创建一个方法,使用二进制搜索查找整数的平方根,如果它不是一个平方数,它应该返回一个整数s,使得s*s=0 * *@param n number以查找 *@返回其平方根的整数部分 */ 专用静态int-iSqrt(int-n){ int l=0; int r=n; int m=((l+r+1)/2); //循环不变量 while(Math.abs(m*m-n)>0){ 如果((m)*(m)>n){ r=m; m=((l+r+1)/2); }否则{ l=m; m=((l+r+1)/2

对于赋值,我必须创建一个方法,使用二进制搜索查找整数的平方根,如果它不是一个平方数,它应该返回一个整数s,使得s*s=0 * *@param n number以查找 *@返回其平方根的整数部分 */ 专用静态int-iSqrt(int-n){ int l=0; int r=n; int m=((l+r+1)/2); //循环不变量 while(Math.abs(m*m-n)>0){ 如果((m)*(m)>n){ r=m; m=((l+r+1)/2); }否则{ l=m; m=((l+r+1)/2); } } 返回m; } 公共静态void main(字符串[]args){ //卡住 系统输出打印LN(iSqrt(15)); //正确计算 系统输出打印LN(iSqrt(16)); } }
对于平方数,它返回正确的数字,但是对于其他整数,它会陷入一个无止境的循环中。我知道问题出在while条件下,但我无法计算出应该放什么,因为随着数字变大,平方数之间的差距变得越来越大(所以我不能只说差距必须低于阈值)。这个练习是关于不变量的,如果这有帮助的话(因此它是以这种方式设置的)。谢谢。

想想看:
Math.abs(m*m-n)>0
总是真的非平方数,因为它从来都不是零,
.abs
不能是负数。这是你的循环条件,这就是为什么循环永远不会结束


这是否为您提供了足够的信息以使您能够继续工作?

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


尝试
while((m+1)*(m+1),正如Ken Bloom所说,你必须有一个错误marge,1。我已经测试了这段代码,它按预期运行了15年。你还需要使用float,我认为这个算法不可能用于int(尽管我没有数学证明)

#定义ε0.0000001
双msqrt(双n){
断言(n>=0);
如果(n==0 | | n==1){
返回n;
}
双低=1,高=n;
双中=(低+高)/2.0;
while(abs(mid*mid-n)>ε){
中等=(低+高)/2.0;
如果(中间*中间
如上所示,您应该简单地应用二进制搜索(二分法) 你可以最小化Epsilon来得到更精确的结果,但这需要更多的时间来运行。
编辑:我在C++编写了代码(对不起)

使用It的问题是,在算法中需要的误差矩阵随着你想知道的平方根的数量越来越大。
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));
    }
}
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;

}
#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;}