Quote:
|
Originally Posted by bludstayne
Why isn't this working? I always get a value that's too high. 4 would give me the correct value, but 9 up always goes over. It's kind of weird too, every perfect square makes it go over a little less, you can check it out and see what I mean.
Code:
float sqrt(unsigned int tar, float accr)
{
float i;
for (i=0.0f;i<tar;i+=accr)
{
if (i*i >= tar)
return i;
}
}
|
Now, to answer your original question:
It is always high due to the >= that you have in the 'if' statement. It won't return a value until it becomes equal or GREATER THAN your value. The odds of it being equal are quite low. Therefore, you're always going to get something that is higher. In fact, it is IMPOSSIBLE to get a value that is lower than the actual square root.
I see two ways to increase your accuracy (I could probably come up with more, but I just woke up).
The first is to make 'accr' smaller. This will give you more accuracy. However, this will also result in slower code.
Here is another way the should give you decent accuracy without much more computation: linearly interpolate between the two points surrounding the square root. Here is an example:
Code:
float sqrt(unsigned int tar, float accr)
{
float i;
float i_prev;
for (i=0.0f;i<tar;i+=accr)
{
if (i*i >= tar)
break;
i_prev = i;
}
// return a linearly interpolated value
return (tar*tar - i_prev*i_prev)/(i*i - i_prev*i_prev) *
(i - i_prev) + i_prev;
}
If you don't want to get that complicated, just average the two values surrounding your target:
Code:
float sqrt(unsigned int tar, float accr)
{
float i;
float i_prev;
for (i=0.0f;i<tar;i+=accr)
{
if (i*i >= tar)
break;
i_prev = i;
}
// return the average of the point before and the point after the sqrt
return (i + i_prev)/2;
}