尝试使用二进制搜索计算出数字的平方根,但是我的实现不起作用,我不知道为什么 - 任何帮助表示感谢,谢谢
继承我的代码。 '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;
}
}
答案 0 :(得分:7)
除了代码中的逻辑问题之外,比较浮点数也不是一个好习惯。
mid * mid == end
可能总是会失败,即使对于sqrt(9)也是如此,因为it is very difficult to test floating-point numbers for equality。
使用范围(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;
}
答案 1 :(得分:1)
我没有修复你的代码,只是解释我将如何编写代码。
使用表示解决方案包围的不变量:
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
是一个完美的正方形时,您可能会认为提前终止可以缩短执行时间。但实际上,大多数输入数字都不是完美的正方形,你将进行两次测试而不是一次,这使得程序平均变慢。
答案 2 :(得分:0)
当然最后一行应该是
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 )
答案 3 :(得分:0)
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;
}
}
}
答案 4 :(得分:0)
您应该用
替换最后一行end = mid -1
在其他代码段中