views:

1827

answers:

3

Homework question:

  • Cygwin GNU GDB
  • Cygwin GNU GCC

Attempting to establish the length of the hypotenuse C from the square root of A power of 2 and B power of 2.

Example input:

Enter the length of two sides of a right-angled triangle: 2.25 8.33

Answer:

The length of the hypotenuse is: 8.628523

  • Question: when I specify the same input as above, the result is not the same - output is 19.84.9596

Full code below:

float squareRoots(float *s)
{
 float cx;
 float nx;
 float e;

 cx = 1;
 nx = (cx +*s/cx)/2;
 e = nx - cx;
 cx = nx;

 if (e*e > 0.001)
 {
  nx = (cx +*s/cx)/2;
  return nx;
 } else {
  return nx;
 }
}

float hypotenuse(float *a, float *b)
{
 float c;
 //raise a to power of 2
 *a = (*a * *a);
 *b = (*b * *b);
 //add a and b
 float y = *a + *b;
 c = squareRoots(&y);

 return c;
}


int main()
{
    float x,y;

    printf("Enter the length of two sides of a right-angled triangle:");
    scanf("%f %f", &x, &y);
    float k=hypotenuse(&x,&y);

    printf("The length of the hypotenuse is: %f", k);

    exit(0);
}
A: 

I make the answer 8.628522469, i.e. 8.628522.

gkrogers
Using the same code? Strange - I'm compiling under cygwin using GNU GDB...
No, you are not compiling with gdb. You're probably compiling with gcc.
Andrew Medico
+3  A: 

Want a super-duper square root implementation? Check out John Carmack's magic square root from Quake III.

float Q_rsqrt( float number )
{
  long i;
  float x2, y;
  const float threehalfs = 1.5F;

  x2 = number * 0.5F;
  y  = number;
  i  = * ( long * ) &y;  // evil floating point bit level hacking
  i  = 0x5f3759df - ( i >> 1 ); // what the ****?
  y  = * ( float * ) &i;
  y  = y * ( threehalfs - ( x2 * y * y ) ); // 1st iteration
  // y  = y * ( threehalfs - ( x2 * y * y ) ); // 2nd iteration, this can be removed

  #ifndef Q3_VM
  #ifdef __linux__
    assert( !isnan(y) ); // bk010122 - FPE?
  #endif
  #endif
  return y;
}
cletus
Unfortunately, I have to use the described algorithm...
Note that this is actually the inverse square root function, so you have to 1/x the result to get the square root.
Bill the Lizard
The "wtf" part will become clear after reading the IEEE spec and figuring out how to write sqrt in terms of log2. Also, papers have been written about the constant used.
Jasper Bekkers
Also, in contrast to common belief, the constant isn't the initial guess. The (i >> 1) part does that plenty. The only thing the constant does is adjust the initial guess.
Jasper Bekkers
+6  A: 

The square root algorithm you're (supposed to be?) using is called Newton's method. Your if statement should be a while loop.

Replace

if (e*e > 0.001)
{
        nx = (cx +*s/cx)/2;
        return nx;
} else {
        return nx;
}

with a while loop that iteratively does the same, but includes recalculating e.

I would give you the working code, but you said this is homework. If you can't get it to work, post your new code and I'll be happy to help you troubleshoot.

Bill the Lizard
@Bill: It's usually called 'Newton–Raphson', at least in most of the refs I've seen :)
Mitch Wheat
Cannot believe I didn't notice this...
Aaron
@Atklin: If you've taken a numerical methods course recently, you should have. :)
Bill the Lizard