View Single Post
  #5   Spotlight this post!  
Unread 15-02-2004, 09:17
Chris Hibner's Avatar Unsung FIRST Hero
Chris Hibner Chris Hibner is offline
Eschewing Obfuscation Since 1990
AKA: Lars Kamen's Roadie
FRC #0051 (Wings of Fire)
Team Role: Engineer
 
Join Date: May 2001
Rookie Year: 1997
Location: Canton, MI
Posts: 1,488
Chris Hibner has a reputation beyond reputeChris Hibner has a reputation beyond reputeChris Hibner has a reputation beyond reputeChris Hibner has a reputation beyond reputeChris Hibner has a reputation beyond reputeChris Hibner has a reputation beyond reputeChris Hibner has a reputation beyond reputeChris Hibner has a reputation beyond reputeChris Hibner has a reputation beyond reputeChris Hibner has a reputation beyond reputeChris Hibner has a reputation beyond repute
Re: Square Root Function not working

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;
}
__________________
-
An ounce of perception is worth a pound of obscure.