I have written a program that computes an estimated value of sqrt(x):
Explanation of the code below
I'm trying to find the nearest number (S) to (x) which can be represented as S=sqrt*sqrt, keep looping until fabs(_sqrt - sqrt) >= 1e-8
is not correct that means that sqrt and _sqrt are very close.
#include <stdio.h>
#include <stdlib.h>
int main (int argc, char *argv[]) {
double val, min, max;
double sqrt;
double S, _sqrt;
int cnt = 0;
// enter an argument,
if (argc < 2) {
printf ("Usage: sqrt < number >\n");
return 1;
}
val = fabs (atof (argv[1]));
min = 0;//minimum
max = sqrt = val;//maximum
_sqrt = 1;
//1e-8 = 10^(-8) = 0.00000001
while (fabs(_sqrt - sqrt) >= 1e-8) {
_sqrt = sqrt;//keep the old sqrt
sqrt = (max + min) / 2;
S = sqrt * sqrt;
printf("test n(%d)\tsqrt(%lf) = %.6lf\n",++cnt,val, sqrt);
if (S>val){
max = sqrt;//setting max to the current sqrt
} else{
min = sqrt;//setting min to the current sqrt
}//end else
}//end while
puts("");
puts("\t====================================================");
printf ("\tfinal value.\tsqrt(%lf) = %.6lf\n", val, sqrt);
puts("\t====================================================");
return 0;
}//end main()
the output
[ar.lnx@host square-root] $ ./sqrt 2
test n(1) sqrt(2.000000) = 1.000000
test n(2) sqrt(2.000000) = 1.500000
test n(3) sqrt(2.000000) = 1.250000
test n(4) sqrt(2.000000) = 1.375000
test n(5) sqrt(2.000000) = 1.437500
test n(6) sqrt(2.000000) = 1.406250
test n(7) sqrt(2.000000) = 1.421875
test n(8) sqrt(2.000000) = 1.414062
test n(9) sqrt(2.000000) = 1.417969
test n(10) sqrt(2.000000) = 1.416016
test n(11) sqrt(2.000000) = 1.415039
test n(12) sqrt(2.000000) = 1.414551
test n(13) sqrt(2.000000) = 1.414307
test n(14) sqrt(2.000000) = 1.414185
test n(15) sqrt(2.000000) = 1.414246
test n(16) sqrt(2.000000) = 1.414215
test n(17) sqrt(2.000000) = 1.414200
test n(18) sqrt(2.000000) = 1.414207
test n(19) sqrt(2.000000) = 1.414211
test n(20) sqrt(2.000000) = 1.414213
test n(21) sqrt(2.000000) = 1.414214
test n(22) sqrt(2.000000) = 1.414214
test n(23) sqrt(2.000000) = 1.414213
test n(24) sqrt(2.000000) = 1.414214
test n(25) sqrt(2.000000) = 1.414214
test n(26) sqrt(2.000000) = 1.414214
test n(27) sqrt(2.000000) = 1.414214
test n(28) sqrt(2.000000) = 1.414214
====================================================
final value. sqrt(2.000000) = 1.414214
====================================================
but it works only for every x>=1, if i want to calculate the sqrt of 0.5 or 0.254 or 0.1... it not works!
[ar.lnx@host square-root] $ ./sqrt1 0.5
test n(1) sqrt(0.500000) = 0.250000
test n(2) sqrt(0.500000) = 0.375000
test n(3) sqrt(0.500000) = 0.437500
test n(4) sqrt(0.500000) = 0.468750
test n(5) sqrt(0.500000) = 0.484375
test n(6) sqrt(0.500000) = 0.492188
test n(7) sqrt(0.500000) = 0.496094
test n(8) sqrt(0.500000) = 0.498047
test n(9) sqrt(0.500000) = 0.499023
test n(10) sqrt(0.500000) = 0.499512
test n(11) sqrt(0.500000) = 0.499756
test n(12) sqrt(0.500000) = 0.499878
test n(13) sqrt(0.500000) = 0.499939
test n(14) sqrt(0.500000) = 0.499969
test n(15) sqrt(0.500000) = 0.499985
test n(16) sqrt(0.500000) = 0.499992
test n(17) sqrt(0.500000) = 0.499996
test n(18) sqrt(0.500000) = 0.499998
test n(19) sqrt(0.500000) = 0.499999
test n(20) sqrt(0.500000) = 0.500000
test n(21) sqrt(0.500000) = 0.500000
test n(22) sqrt(0.500000) = 0.500000
test n(23) sqrt(0.500000) = 0.500000
test n(24) sqrt(0.500000) = 0.500000
test n(25) sqrt(0.500000) = 0.500000
test n(26) sqrt(0.500000) = 0.500000
====================================================
final value. sqrt(0.500000) = 0.500000
====================================================
Can someone help me understand what the problem is and how to fix it?
The problem is that you're initializing max
to val
. For numbers less than 1, the square root will be greater than the number, not less. For instance, for 0.5 the square root is 0.707... A simple fix would be to initialize max
to 1 if val
is less than 1.
The reason is that your conversion logic only works if val > 1
Note the way you test the sqrt(.5)
Since when val == 0.5
you get S = val * val
which is 0.25
. This resets min
to 0.25
Since sqrt = (max + min) / 2;
and the initial max
is val
(0.5) you can never get past 0.5
.
You will have to determine that since your initial val
is less than 1, you want your initial max
to be 1 so that your average is val < sqrt < 1
If you do this, then you should converge on the correct value.
I do not have access to a C compiler at this time. However, by initial inspection the first average is 1.5/2 == .75
which resets max. The new average is 1.25/2 == .625
which resets min You should then continue until you converge on the correct value.
FYI you can also use the contents of the while loop as a different function in order to teach yourself recursion. That is, instead of looping through the while, if S > lim {call the new estimate function} once it falls through the recursion, it will pass the final estimate back up to the initial calling function.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With