Reputation: 61
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
Upvotes: 1
Views: 257
Reputation: 153527
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:
Determine the the side with the largest magnitude squared - the candidate hypotenuse squared. This negates the need for square root and absolute value.
Sum the other 2 squares.
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()
.
Upvotes: 2