Go to Post I might be a nerd, but I am definitely a pi freak! - Courtneyb1023 [more]
Home
Go Back   Chief Delphi > Technical > Programming
CD-Media   CD-Spy  
portal register members calendar search Today's Posts Mark Forums Read FAQ rules

 
Closed Thread
Thread Tools Rate Thread Display Modes
  #1   Spotlight this post!  
Unread 14-02-2004, 14:01
bludstayne's Avatar
bludstayne bludstayne is offline
Registered User
#0547
 
Join Date: Nov 2003
Location: Fayetteville, TN
Posts: 10
bludstayne has a little shameless behaviour in the past
Send a message via AIM to bludstayne Send a message via Yahoo to bludstayne
Square Root Function not working

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;
    }
}
__________________
I hate signatures. I wouldn't even consider having one.
  #2   Spotlight this post!  
Unread 14-02-2004, 14:52
Paul Paul is offline
lacks sanity
FRC #0316 (LuNaTeCs)
Team Role: College Student
 
Join Date: Jan 2003
Rookie Year: 2002
Location: Salem,NJ
Posts: 14
Paul is an unknown quantity at this point
Send a message via AIM to Paul
Cool Re: Square Root Function not working

http://www.chiefdelphi.com/forums/sh...618#post221618
I responded to your origonal post. See if it helps you out any.
  #3   Spotlight this post!  
Unread 14-02-2004, 22:33
seanwitte seanwitte is offline
Registered User
None #0116
Team Role: Engineer
 
Join Date: Nov 2002
Location: Herndon, VA
Posts: 378
seanwitte has a brilliant futureseanwitte has a brilliant futureseanwitte has a brilliant futureseanwitte has a brilliant futureseanwitte has a brilliant futureseanwitte has a brilliant futureseanwitte has a brilliant futureseanwitte has a brilliant futureseanwitte has a brilliant futureseanwitte has a brilliant futureseanwitte has a brilliant future
Send a message via AIM to seanwitte
Re: Square Root Function not working

This code is based on an algorithm I found on Microchip's web site. Its for 32 bit integers, but can be adapted for 24 and 16 bit ints by changing the mask and result values.

Code:
typedef unsigned long uint32;

uint32 sqrt32(uint32 x)
{	
	uint32 mask = 0x1000;
	uint32 result = 0x800;

	while (mask > 0)
	{
		if ((result * result) > x)
		{
			result &= (~mask);
		}
		mask >>= 1;
		result |= mask;
	}
	return result;
}
  #4   Spotlight this post!  
Unread 15-02-2004, 08:50
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.
Do you really need a sqare root? We originally had a square root in our waypoint calculation (to determine the distance from us to the waypoint), but we determined the square root was unessecary. Why? Because we're using feedback control to get to the position AND x^2 + y^2 becomes zero at the same point as sqrt(x^2 + y^2). Anyway, it's just a thought - you may not need the square root afterall.

-Chris
__________________
-
An ounce of perception is worth a pound of obscure.
  #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.
  #6   Spotlight this post!  
Unread 15-02-2004, 09:41
kiracofe8 kiracofe8 is offline
Registered User
#1317 (Digital Fusion)
Team Role: Engineer
 
Join Date: Nov 2001
Location: Columbus, OH
Posts: 30
kiracofe8 will become famous soon enough
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;
    }
}
Why this goes over has already been answered, but I should also point out that this algorithm will be incredibly slow, and not particularly accurate. Two things:

First off, it is a cardinal sin to have a floating point value as a loop index. The problem is that floating point numbers always have some round off error. And, each time you add, the round off error increases. So, for example, if tar = 1, and accr = 0.1, after 10 iterations, you may get i = 0.9999999 or you may get i = 1.0000001. If you get the former, you'll end up with the square of 1 = 1.1 b/c you'll go one step too far. If you get the later, you'll get the right answer. But there is no way to know which you'll get ahead of time.

The problem of floating point loop indexes can cause such subtle bugs that some languages do not allow it at all (e.g. recent versions of FORTRAN). The following is the recommended replacement:

Code:
float sqrt(unsigned int tar, float accr)
{
    int i;
    float j;

    j = 0;

    for (i=0;j<tar;i++)
    {
        j = i * accr;
        if (j*j >= tar)
            return j;
    }
    return -1; //signal an error.  should never happen, but it is bad form to
                  //simply not return any value.    
}
Secondly: the algorithm itself converges slowly. E.g. if you try to take the square root of, say, 100 with accr = 0.1, it will take a LONG time (1000 iterations) to get a correct answer. Try a different method. The most common method to numerically compute square roots is called Newton's method. Do a search on google for "Newton's method square root" and you should find some good example code. Newton's method will converge to a reasonable value after only a few iterations.
__________________
/* Daniel */
  #7   Spotlight this post!  
Unread 15-02-2004, 11:23
Paul Paul is offline
lacks sanity
FRC #0316 (LuNaTeCs)
Team Role: College Student
 
Join Date: Jan 2003
Rookie Year: 2002
Location: Salem,NJ
Posts: 14
Paul is an unknown quantity at this point
Send a message via AIM to Paul
Talking Re: Square Root Function not working

Quote:
Originally Posted by kiracofe8
Why this goes over has already been answered, but I should also point out that this algorithm will be incredibly slow, and not particularly accurate. Two things:

First off, it is a cardinal sin to have a floating point value as a loop index. The problem is that floating point numbers always have some round off error. And, each time you add, the round off error increases. So, for example, if tar = 1, and accr = 0.1, after 10 iterations, you may get i = 0.9999999 or you may get i = 1.0000001. If you get the former, you'll end up with the square of 1 = 1.1 b/c you'll go one step too far. If you get the later, you'll get the right answer. But there is no way to know which you'll get ahead of time.

The problem of floating point loop indexes can cause such subtle bugs that some languages do not allow it at all (e.g. recent versions of FORTRAN). The following is the recommended replacement:

Code:
float sqrt(unsigned int tar, float accr)
{
    int i;
    float j;

    j = 0;

    for (i=0;j<tar;i++)
    {
        j = i * accr;
        if (j*j >= tar)
            return j;
    }
    return -1; //signal an error.  should never happen, but it is bad form to
                  //simply not return any value.    
}
Secondly: the algorithm itself converges slowly. E.g. if you try to take the square root of, say, 100 with accr = 0.1, it will take a LONG time (1000 iterations) to get a correct answer. Try a different method. The most common method to numerically compute square roots is called Newton's method. Do a search on google for "Newton's method square root" and you should find some good example code. Newton's method will converge to a reasonable value after only a few iterations.
I've used Newton's system of finding square roots, and it is pretty fast. Take a look at this code, it only works for ints but it should be good enough for what you need. It takes a a number of interations equal to the square root. For instance, to get the sqr of 16 it would take 4 interations, 100 would be 10 and so on and so forth. See how you like it.

inline int sroot(int n)
{
int c = 0; int a = 1;
do {n -= a; a += 2; ++c;}
while (n > 0);
return c;
}

Last edited by Paul : 15-02-2004 at 11:31.
  #8   Spotlight this post!  
Unread 15-02-2004, 12:09
mtrawls's Avatar
mtrawls mtrawls is offline
I am JVN! (John von Neumann)
#0122 (NASA Knights)
Team Role: Programmer
 
Join Date: Mar 2003
Location: Hampton, VA
Posts: 295
mtrawls is a splendid one to beholdmtrawls is a splendid one to beholdmtrawls is a splendid one to beholdmtrawls is a splendid one to beholdmtrawls is a splendid one to beholdmtrawls is a splendid one to beholdmtrawls is a splendid one to behold
Send a message via AIM to mtrawls
Re: Square Root Function not working

Quote:
Originally Posted by Chris Hibner
Do you really need a sqare root? We originally had a square root in our waypoint calculation (to determine the distance from us to the waypoint), but we determined the square root was unessecary. Why? Because we're using feedback control to get to the position AND x^2 + y^2 becomes zero at the same point as sqrt(x^2 + y^2). Anyway, it's just a thought - you may not need the square root afterall.

-Chris
If you do find you need to compute sqrt(x^2+y^2), might I suggest the CORDIC algorithm (mentioned here before for sin/cos by Kevin Watson, I believe ... I found it very useful). Here is a very good file explaining it: http://www.andraka.com/files/crdcsrvy.pdf. The nice thing about it, is that it is a "shift and add" algorithm ... which is very fast. Maybe I'm just wierd, but I thought it was cool, and was disappointed when I realized we wouldn't be using it ... like Chris said he didn't need to compute the sqrt, we figured that we might not need to compute trig functions ourselves either.
Closed Thread


Thread Tools
Display Modes Rate This Thread
Rate This Thread:

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Forum Jump

Similar Threads
Thread Thread Starter Forum Replies Last Post
Mulit-postioning with pnuematics this year? KenWittlief Pneumatics 101 01-02-2005 21:54
Square Root bludstayne Programming 3 14-02-2004 14:48
Aspartame shyra1353 Chit-Chat 8 20-01-2004 22:41
I'm working :) Jack FIRST Scouting Network 2 03-01-2004 01:26
Whose working this summer? Frank(Aflak) Chit-Chat 20 28-05-2003 11:35


All times are GMT -5. The time now is 10:46.

The Chief Delphi Forums are sponsored by Innovation First International, Inc.


Powered by vBulletin® Version 3.6.4
Copyright ©2000 - 2017, Jelsoft Enterprises Ltd.
Copyright © Chief Delphi