Improved (optimized) version
- Find the largest side and the smallest side. (Without loss of generality, we call them C and A). And B is the third party.
- Now C 2 - A 2 = B 2 for a right triangle. (C + A) * (CA) = B 2 calculate unsigned_sum = C + A and unsigned_diff = CA (unsigned int will not overflow for the sum
int ) - Separate the sum, diff and B with gcd sum and diff. If he does not divide B, it is not a right triangle. If so, the sum and diff will be perfect squares if the triangle is right.
- Find the integer square root of the sum and diff. If the product of the roots is B, the triangle is right.
int is_right_triangle(int a, int b, int c) { unsigned int sum, diff; int f = 2; unsigned int hcf, irts, irtd; if(b > c) swap(&b, &c); if(a > b) swap(&a, &b); if(b > c) swap(&b, &c); sum = c; diff = c; sum += a; diff -= a; hcf = gcd(sum, diff); if(b % hcf != 0) return 0; sum /= hcf; diff /= hcf; b /= hcf; irts = isqrt(sum); if(irts * irts != sum || b % irts != 0) return 0; b /= irts; irtd = isqrt(diff); if(irtd * irtd != diff || b % irtd != 0) return 0; b /= irtd; return b == 1; }
You can find an algorithm for isqrt @ Methods_of_computing_square_roots or use the binary search method.
#define NEXT(n, i) (((n) + (i)/(n)) >> 1) unsigned int isqrt(int number) { unsigned int n = 1; unsigned int n1 = NEXT(n, number); while(abs(n1 - n) > 1) { n = n1; n1 = NEXT(n, number); } while(n1*n1 > number) n1--; return n1; }
isqrt copied unchanged from codecodex
Old answer
- Find the largest side and the smallest side. (Without loss of generality, we call them C and A). And B is the third party.
- Now C 2 - A 2 = B 2 for a right triangle. (C + A) * (CA) = B 2 calculate unsigned_sum = C + A and unsigned_diff = CA (unsigned int will not overflow for the sum
int ) - Collect the main factors unsigned_sum and unsigned_diff. If they are not a multiple of 2, this is not correct at an angle. If the odds are a multiple of 2, continue to divide copy_of_B = B, once per couple of key factors. (Check that fac * fac <max (unsigned_sum, unsigned_dif), if the delimiter is also divisible, try splitting with another as well)
- If B = 1 at the end, the triangle was at right angles, otherwise it is not.
int is_right_triangle(int a, int b, int c) { unsigned int sum, diff; int f = 2; if(b > c) swap(&b, &c); if(a > b) swap(&a, &b); if(b > c) swap(&b, &c); sum = c; diff = c; sum += a; diff -= a; while(f * f <= sum || f * f <= diff) { int count = 0; while(sum % f == 0) { sum /= f; ++count; } while(diff % f == 0) { diff /= f; ++count; } if(count % 2 == 1) return 0; while(count != 0) { b /= f; count -= 2; } ++f; } return b == 1; }
Optimization
1. As mentioned in this comment , you can separate unsigned_sum, unsigned_diff and b with gcd (unsigned_sum, unsigned_diff) and separately handle unsigned_sum and unsigned_diff.
2. In the loop, if you can check at any point that the product sum and diff (and square b) are guaranteed not to overflow, you can check sum * diff == (unsigned)b * b and break accordingly.
Mohit jain
source share