Trying to determine if a triangle is a right triangle in C using the Epsilon rule

174 Views Asked by At
  • I've been making this code to determine if a triangle can be a right triangle without using sqrt() or abs() by taking three sides and figuring out if the absolute difference between them is less than Epsilon, or 0.05. But it only works in some cases. What am I doing wrong?
int IsRightTriangle(float side1, float side2, float side3)
{
    if (side3*side3-(side1*side1+side2*side2) <= 0.05 || side3*side3-(side1*side1+side2*side2) >= -0.05) {
        return 1;
    }
    else if (side1*side1-(side3*side3+side2*side2) <= 0.05 || side1*side1-(side3*side3+side2*side2) >= -0.05) {
        return 1;
    }
    else if (side2*side2-(side3*side3+side1*side1) <= 0.05 || side2*side2-(side3*side3+side1*side1) >= -0.05) {
        return 1;
    }
    else 
        return 0;
}

I have tried multiple iterations of this code, and they all got results similar to this:


Running test: IsRightTriangle(edge1=15.00, edge2=27.00, edge3=29.55)  --  Passed
Running test: IsRightTriangle(edge1=21.02, edge2=19.00, edge3=9.00)  --  Failed

1

There are 1 best solutions below

0
On

What am I doing wrong?

I'd expect && instead of || as the compare needs to meet both conditions to be a "right" triangle.

Think of

if (side3*side3-(side1*side1+side2*side2) <= 0.05 || side3*side3-(side1*side1+side2*side2) >= -0.05) { 
    return 1;
}

as

double d = side3*side3-(side1*side1+side2*side2);
if (d <= 0.05 || d >= -0.05) {
    return 1;
}

d <= 0.05 || d >= -0.05 is always true (unless sides had a not-a-number).
Certain it should use d <= 0.05 && d >= -0.05.
Other issues exist too.


Trying to determine if a triangle is a right triangle

Suggested alternative algorithm:

  1. Determine the the side with the largest magnitude squared - the candidate hypotenuse squared. This negates the need for square root and absolute value.

  2. Sum the other 2 squares.

  3. Relatively compare the two for nearness to 1.0 (a right triangle).
    Code is dealing with floating point values.
    IsRightTriangle(15.00 , 27.00 , 29.55) should get the same result as
    IsRightTriangle(15.00e10 , 27.00e10 , 29.55e10) and as
    IsRightTriangle(15.00e-10, 27.00e-10, 29.55e-10).

Example: Lightly tested sample code:

int IsRightTriangle(float side1, float side2, float side3) {
  double sq[3];
  sq[0] = 1.0 * side1 * side1; // Use double math for extra precision and range.
  sq[1] = 1.0 * side2 * side2;
  sq[2] = 1.0 * side3 * side3;

  if (sq[1] < sq[2]) {
    swap(&sq[1], &sq[2]);
  }
  if (sq[0] < sq[1]) {
    swap(&sq[0], &sq[1]);
  }
  // sq[0] is now the largest.

  double hypotenuse = sq[0];
  double sum_of_smaller2 = sq[1] + sq[2];

  if (hypotenuse == 0.0) {
    return 1; // Degenerate case, all sides 0.
  }

  // How close to 1.0 is sum_of_smaller2/hypotenuse?
  #define Epsilon 0.05
  // Use the square as the we are testing the square of magnitudes.
  #define Epsilon2 (Epsilon * Epsilon)
  double ratio = sum_of_smaller2 / hypotenuse;
  return (1.0 - Epsilon2 <= ratio) && (ratio <= 1.0 + Epsilon2);
}

Notes:

  • double or float? OP is using float arguments, yet double constants and discusses double functions like sqrt() instead of sqrtf().

  • abs() is an integer function and has no place here. Instead discuss fabs(), fabsf().