You have a problem with obtuse triangles, x*x + y*y - z*z
would mathematically give a negative result, that is then reduced modulo 2^WIDTH
(where WIDTH
is the number of value bits in unsigned long long
, at least 64 and probably exactly that) yielding a - probably large - positive value (or in rare cases 0). Then the computed result of t = (x*x + y*y - z*z)/(2*x*y)
can be larger than 1, and acos(t)
would return a NaN.
The correct way to find out whether the triangle is obtuse/acute/right-angled with the given argument type is to check whether x*x + y*y < /* > / == */ z*z
- if you can be sure the mathematical results don't exceed the unsigned long long
range.
If you can't be sure of that, you can either convert the variables to double
before the computation,
double xd = x, yd = y, zd = z;
double t = (xd*xd + yd*yd - zd*zd)/(2*xd*yd);
with possible loss of precision and incorrect results for nearly right-angled triangles (e.g. for the slightly obtuse triangle x = 2^29, y = 2^56-1, z = 2^56+2
, both y
and z
would be converted to 2^56 with standard 64-bit double
s, xd*xd + yd*yd = 2^58 + 2^112
would be evaluated to 2^112
, subtracting zd*zd
then results in 0).
Or you can compare x*x + y*y
to z*z
- or x*x
to z*z - y*y
- using only integer arithmetic. If x*x
is representable as an unsigned long long
(I assume that 0 < x <= y <= z
), it's relatively easy, first check whether (z - y)*(z + y)
would exceed ULLONG_MAX
, if yes, the triangle is obtuse, otherwise calculate and compare. If x*x
is not representable, it becomes complicated, I think the easiest way (except for using a big integer library, of course) would be to compute the high and if necessary low 64 (or whatever width unsigned long long
has) bits separately by splitting the numbers at half the width and compare those.
Further note: Your value for π, 3.14159265
is too inaccurate, right-angled triangles will be reported as obtuse.