when I check for the condition in c1 it should give me 1, but instead it gives me 0
How can I fix this problem?
Change your expectations.
A typical double
can represent exactly about 264 different values. 1.923, 59.240, 61.163 are typically not in that set as double
is usually encoded in a binary way. e.g. binary64.
When a,b,c
are assigned 1.923, 59.240, 61.163, they get values more like the below which are the closet double
.
a 1.923000000000000042632564145606...
b 59.240000000000001989519660128281...
c 61.162999999999996703081706073135...
In my case, the a
, and b
both received a slightly higher value than the decimal code form, while c
received a slightly lower one.
When adding a+b
, the sum was rounded up, further away from c
.
printf("a+b %35.30f\n", a+b);
a+b 61.163000000000003808509063674137
a + b > c
was true, as well as other compares and OP's
checkIfTriangleIsValid(1.923, 59.240, 61.163)
should return valid (0) as it is really more like checkIfTriangleIsValid(1.9230000000000000426..., 59.24000000000000198..., 61.16299999999999670...)
Adding a+b
is further complicated in that the addition may occur using double
or long double
math. Research FLT_EVAL_METHOD
for details. Rounding mode also can affect the final sum.
#include <float.h>
printf("FLT_EVAL_METHOD %d\n", FLT_EVAL_METHOD);
As to an alternative triangle check, subtract the largest 2 values and then compare against the smallest.
a > (c-b)
can preserve significantly more precision than (a+b) > c
.
// Assume a,b,c >= 0
int checkIfTriangleIsValid_2(double a, double b, double c) {
// Sort so `c` is largest, then b, a.
if (c < b) {
double t = b; b = c; c = t;
}
if (c < a) {
double t = a; a = c; c = t;
}
if (a > b) {
double t = b; b = a; a = t;
}
// So far, no loss of precision is expected due to compares/swaps.
// Only now need to check a + b >= c for valid triangle
// To preserve precision, subtract from `c` the value closest to it (`b`).
return a > (c-b);
}
I will review more later as time permits. This approach significant helps for a precise answer - yet need to assess more edge cases. It reports a valid triangle checkIfTriangleIsValid_2(1.923, 59.240, 61.163))
.
FLT_EVAL_METHOD
, rounding mode and double
encoding can result in different answers on other platforms.
Notes:
It appears a checkIfTriangleIsValid()
returning 0 means valid triangle.
It also appears when the triangle has 0 area, the expected result is 1 or invalid.