, когда я проверяю условие в c1, оно должно давать мне 1, но вместо этого оно дает мне 0
Как я могу решить эту проблему?
Измените свои ожидания.
Типичный double
может представлять точно около 2 64 различных значений.1.923, 59.240, 61.163 обычно не входят в этот набор, поскольку double
обычно кодируется двоичным способом.например, binary64 .
Когда a,b,c
назначены 1.923, 59.240, 61.163, они получают значения, более похожие на приведенные ниже, которые представляют собой шкаф double
.
a 1.923000000000000042632564145606...
b 59.240000000000001989519660128281...
c 61.162999999999996703081706073135...
В моем случае a
и b
получили немного более высокое значение, чем форма десятичного кода, в то время как c
получили немного меньшее значение.
При добавлении a+b
суммабыл округлен в большую сторону, дальше от c
.
printf("a+b %35.30f\n", a+b);
a+b 61.163000000000003808509063674137
a + b > c
, а также других сравнений и OP
checkIfTriangleIsValid(1.923, 59.240, 61.163)
должен вернуться Действительный (0) , поскольку это действительно больше похоже на checkIfTriangleIsValid(1.9230000000000000426..., 59.24000000000000198..., 61.16299999999999670...)
Добавление a+b
еще более усложняется тем, что добавление может происходить с использованием double
или long double
математикаИсследование FLT_EVAL_METHOD
для деталей.Режим округления также может повлиять на итоговую сумму.
#include <float.h>
printf("FLT_EVAL_METHOD %d\n", FLT_EVAL_METHOD);
Что касается альтернативной проверки треугольника, вычтите 2 больших значения и затем сравните с наименьшим.
a > (c-b)
может сохранять значительно большую точность, чем (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);
}
Я расскажу подробнее позже, если позволит время.Такой подход существенно помогает получить точный ответ, но при этом необходимо оценить больше крайних случаев.Сообщается действительный треугольник checkIfTriangleIsValid_2(1.923, 59.240, 61.163))
.
FLT_EVAL_METHOD
, режим округления и кодирование double
могут привести к различным ответам на других платформах.
Примечания:
Похоже, checkIfTriangleIsValid()
возвращает 0 означает действительный треугольник .
Также появляется, когда треугольник имеет область 0, ожидаемый результат равен 1 или недействительно .