Подтвердить что ты не робот

Гарантируются ли постоянство поплавкового неравенства

Предположим 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 во время компиляции? Меня интересуют в основном обычные значения, не столько в субнормальных или специальных значениях.

Мне кажется, что это должно зависеть от ошибок округления при вычитании в основном.

4b9b3361

Ответ 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 должны быть конечными, Все контрпримеры имеют, по существу, эту форму.