This was my code:
# include <stdio.h>
float absolute(float x){
return x>0? x: (-1)*x;
}
float bisect(float a, float b){
float k = (a b)*0.5;
return k;
}
//For n>1
float find(float n, float precision){
float l=1,m=n;
float sqrt, k=bisect(l,m);
while(absolute(k*k-n)>precision){
if(k*k-n>0){
m=k;
l=l;
k=bisect(l,m);
}
else if(k*k-n<0)
{l=k;
m=m;
k=bisect(k,m);
}
}
return k;
}
int main(){
float n, precision;
scanf("%f %f", &n, &precision);
printf("%f", find(n, precision));
return 0;
}
Well, it gave me the square root alright, but not up to the precision I specified. For instance, the square root of 3 was given to be 1.734375 and not 1.732050, which is the correct value, in spite of setting the precision equal to 0.001. I spent nearly an hour trying to debug this and now I'm done. Please help me identify where the code went wrong. Thanks in advance!
CodePudding user response:
You use precision to compare k * k and n, while you want the precision for k and not for k * k.
Your while condition should be instead while (m - l > precision) { .... That is the correct way to make sure that the difference between k and the real value is less than precision
CodePudding user response:
You get 1.734375 if you ask for precision 0.01, not 0.001 as you said in your question. Note that your precision is the absolute error you accept in k*k-n, and not the absolute error you accept in sqrt(n) - k. Perhaps that's the source of your confusion?
If you want to bound the absolute error in the result, you can check that if k*k < n, then (k precision)*(k precision) >= n, or if k*k>n, then (k-precision)*(k-precision) <= n.
Or alternatively, you can check that abs(n - k^2 - p^2/4) < pk, where p is the precision. (This is the same as checking that (k-p/2)^2 < n < (k p/2)^2).
