Гарантируются ли постоянство поплавкового неравенства
Предположим a
, b
, c
и d
объявлены double
(или float
). Всегда ли следующие выражения?
! ( (a >= b) && (c <= d) ) || ( (a-c) >= (b-d) )
! ( (a > b) && (c <= d) ) || ( (a-c) > (b-d) )
! ( (a >= b) && (c < d) ) || ( (a-c) > (b-d) )
Есть ли какая-либо гарантия от IEEE 754 или текущего стандарта C или С++? И будет ли любой компилятор оптимизировать это как просто true во время компиляции? Меня интересуют в основном обычные значения, не столько в субнормальных или специальных значениях.
Мне кажется, что это должно зависеть от ошибок округления при вычитании в основном.
Ответы
Ответ 1
Для того, чтобы 3-й создать ложь, должно быть достаточно, чтобы принимать большие равные a
и b
и маленькие неравные c
и d
, например. a=1e30, b=1e30, c=1e-31, d=1e-30
.
EDIT: Ok, для второго, чтобы произвести ложь, по аналогии с 3-м, этого должно быть достаточно, чтобы взять небольшие неравные a
и b
и большие равные c
и d
, например. a=1e-30, b=1e-31, c=1e30, d = 1e30
.
Не знаю о контрпример для первого выражения...
Ответ 2
Серж Рогэтт дал контрпримеры вашему второму и третьему выражениям.
Первая, !(a >= b && c <= d) || a-c >= b-d
, всегда верна в арифметике IEEE 754, если a
, b
, c
и d
должны быть конечными. Вычитание конечных чисел не может дать a NaN
. Таким образом, контрпример должен удовлетворять a >= b && c <= d && a-c < b-d
. Однако a >= b
означает, что a-c >= b-c
, независимо от c
, и c <= d
подразумевает, что b-c >= b-d
, независимо от b
. Транзитивность >=
заботится обо всем остальном.
Вы можете взять a = c = 1.0/0.0
и взять произвольный выбор b
и d
для контрпримера, если вы расслабляете условие, что a
, b
, c
и d
должны быть конечными, Все контрпримеры имеют, по существу, эту форму.