Java 平方根的二进制搜索[家庭作业]
对于赋值,我必须创建一个方法,使用二进制搜索查找整数的平方根,如果它不是一个平方数,它应该返回一个整数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)); } }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
对于平方数,它返回正确的数字,但是对于其他整数,它会陷入一个无止境的循环中。我知道问题出在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;}