对于赋值,我必须使用二进制搜索创建一个方法来查找整数的平方根,如果它不是一个平方数,它应该返回一个整数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条件,但由于数字变得越大,方形数字之间的差距变得越大,我无法确定要放什么(所以我不能把它放在那里差距必须低于阈值)。这项练习是关于不变量的,如果它有帮助的话(因此它以这种方式设置)。谢谢。
答案 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;
}